• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #ifdef STDC_HEADERS
6 # include <stdlib.h>
7 # include <string.h>
8 #else
9 # ifndef HAVE_STRCHR
10 #  define strchr index
11 #  define strrchr rindex
12 # endif
13 char   *strchr(), *strrchr();
14 # ifndef HAVE_MEMCPY
15 #  define memcpy(d, s, n) bcopy ((s), (d), (n))
16 #  define memmove(d, s, n) bcopy ((s), (d), (n))
17 # endif
18 #endif
19 
20 #if defined(HAVE_NCURSES_TERMCAP_H)
21 # include <ncurses/termcap.h>
22 #elif defined(HAVE_TERMCAP_H)
23 # include <termcap.h>
24 #elif defined(HAVE_TERMCAP)
25 # include <curses.h>
26 # if !defined(__bsdi__)
27 #  include <term.h>
28 # endif
29 #endif
30 
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include "console.h"
34 #include "main.h"
35 
36 #ifdef WITH_DMALLOC
37 #include <dmalloc.h>
38 #endif
39 
40 #define CLASS_ID           0x434F4E53
41 #define REPORT_BUFF_SIZE   1024
42 
43 #if defined(_WIN32)  &&  !defined(__CYGWIN__)
44 # include <windows.h>
45 #endif
46 
47 
48 /*
49  * Taken from Termcap_Manual.html:
50  *
51  * With the Unix version of termcap, you must allocate space for the description yourself and pass
52  * the address of the space as the argument buffer. There is no way you can tell how much space is
53  * needed, so the convention is to allocate a buffer 2048 characters long and assume that is
54  * enough.  (Formerly the convention was to allocate 1024 characters and assume that was enough.
55  * But one day, for one kind of terminal, that was not enough.)
56  */
57 
58 #ifdef HAVE_TERMCAP
59 
60 static void
get_termcap_string(char const * id,char * dest,size_t n)61 get_termcap_string(char const* id, char* dest, size_t n)
62 {
63     char    tc[16];
64     char   *tp = tc;
65     tp[0] = '\0';
66     tp = tgetstr(id, &tp);
67     if (tp != NULL && dest != NULL && n > 0) {
68         strncpy(dest, tp, n);
69         dest[n-1] = '\0';
70     }
71 }
72 
73 static void
get_termcap_number(char const * id,int * dest,int low,int high)74 get_termcap_number(char const* id, int* dest, int low, int high)
75 {
76     int const val = tgetnum(id);
77     if (low <= val && val <= high) {
78         *dest = val;
79     }
80 }
81 
82 static void
apply_termcap_settings(Console_IO_t * const mfp)83 apply_termcap_settings(Console_IO_t * const mfp)
84 {
85     /* try to catch additional information about special console sequences */
86     char const* term_name = getenv("TERM");
87     if (NULL != term_name) {
88         char    term_buff[4096];
89         int const ret = tgetent(term_buff, term_name);
90         if (1 == ret) {
91             get_termcap_number("co", &mfp->disp_width, 40, 512);
92             get_termcap_number("li", &mfp->disp_height, 16, 256);
93             get_termcap_string("up", mfp->str_up, sizeof(mfp->str_up));
94             get_termcap_string("md", mfp->str_emph, sizeof(mfp->str_emph));
95             get_termcap_string("me", mfp->str_norm, sizeof(mfp->str_norm));
96             get_termcap_string("ce", mfp->str_clreoln, sizeof(mfp->str_clreoln));
97         }
98     }
99 }
100 #endif /* TERMCAP_AVAILABLE */
101 
102 static int
is_console_initialized(Console_IO_t * const mfp)103 is_console_initialized(Console_IO_t * const mfp)
104 {
105     return mfp && mfp->ClassID == CLASS_ID ? 1 : 0;
106 }
107 
108 static int
init_console(Console_IO_t * const mfp)109 init_console(Console_IO_t * const mfp)
110 {
111     if (is_console_initialized(mfp)) {
112         return 0; /* already initialized */
113     }
114     /* setup basics of brhist I/O channels */
115     mfp->disp_width = 80;
116     mfp->disp_height = 25;
117     mfp->Console_fp = stderr;
118     mfp->Error_fp = stderr;
119     mfp->Report_fp = NULL;
120 
121     /*mfp -> Console_buff = calloc ( 1, REPORT_BUFF_SIZE ); */
122     setvbuf(mfp->Console_fp, mfp->Console_buff, _IOFBF, sizeof(mfp->Console_buff));
123 /*  setvbuf ( mfp -> Error_fp  , NULL                   , _IONBF, 0                                ); */
124 
125 #if defined(_WIN32)  &&  !defined(__CYGWIN__)
126     mfp->Console_Handle = GetStdHandle(STD_ERROR_HANDLE);
127 #endif
128 
129     strcpy(mfp->str_up, "\033[A");
130 
131 #ifdef HAVE_TERMCAP
132     apply_termcap_settings(mfp);
133 #endif /* TERMCAP_AVAILABLE */
134 
135     mfp->ClassID = CLASS_ID;
136 
137 #if defined(_WIN32)  &&  !defined(__CYGWIN__)
138     mfp->Console_file_type = GetFileType(Console_IO.Console_Handle);
139 #else
140     mfp->Console_file_type = 0;
141 #endif
142     return 0;
143 }
144 
145 static void
deinit_console(Console_IO_t * const mfp)146 deinit_console(Console_IO_t * const mfp)
147 {
148     if (!is_console_initialized(mfp)) {
149         return; /* not initialized or already de-initialized */
150     }
151     if (mfp->Report_fp != NULL) {
152         fclose(mfp->Report_fp);
153         mfp->Report_fp = NULL;
154     }
155     fflush(mfp->Console_fp);
156     setvbuf(mfp->Console_fp, NULL, _IONBF, (size_t) 0);
157 
158     memset(mfp->Console_buff, 0x55, REPORT_BUFF_SIZE);
159 }
160 
161 /*  LAME console
162  */
163 Console_IO_t Console_IO;
164 
165 enum ConsoleEnum { ConsoleIoConsole, ConsoleIoError, ConsoleIoReport };
166 
167 static FILE*
frontend_console_file_handle(enum ConsoleEnum e)168 frontend_console_file_handle(enum ConsoleEnum e)
169 {
170     if (is_console_initialized(&Console_IO)) {
171         switch (e) {
172         case ConsoleIoConsole:  return Console_IO.Console_fp;
173         case ConsoleIoError:    return Console_IO.Error_fp;
174         case ConsoleIoReport:   return Console_IO.Report_fp;
175         }
176     }
177     return 0;
178 }
179 
180 static int
frontend_console_print(const char * format,va_list ap,enum ConsoleEnum e)181 frontend_console_print(const char *format, va_list ap, enum ConsoleEnum e)
182 {
183     FILE    *fp = frontend_console_file_handle(e);
184 
185     if (fp != NULL)
186         return vfprintf(fp, format, ap);
187     return 0;
188 }
189 
190 static void
frontend_console_flush(enum ConsoleEnum e)191 frontend_console_flush(enum ConsoleEnum e)
192 {
193     FILE    *fp = frontend_console_file_handle(e);
194 
195     if (fp != NULL)
196         fflush(fp);
197 }
198 
199 int
frontend_open_console(void)200 frontend_open_console(void)
201 {
202     return init_console(&Console_IO);
203 }
204 
205 void
frontend_close_console(void)206 frontend_close_console(void)
207 {
208     deinit_console(&Console_IO);
209 }
210 
211 void
frontend_debugf(const char * format,va_list ap)212 frontend_debugf(const char *format, va_list ap)
213 {
214     (void) frontend_console_print(format, ap, ConsoleIoReport);
215 }
216 
217 void
frontend_msgf(const char * format,va_list ap)218 frontend_msgf(const char *format, va_list ap)
219 {
220     (void) frontend_console_print(format, ap, ConsoleIoConsole);
221 }
222 
223 void
frontend_errorf(const char * format,va_list ap)224 frontend_errorf(const char *format, va_list ap)
225 {
226     (void) frontend_console_print(format, ap, ConsoleIoError);
227 }
228 
229 void
frontend_print_null(const char * format,va_list ap)230 frontend_print_null(const char *format, va_list ap)
231 {
232     (void) format;
233     (void) ap;
234 }
235 
236 int
console_printf(const char * format,...)237 console_printf(const char *format, ...)
238 {
239     va_list args;
240     int     ret;
241 
242     va_start(args, format);
243     ret = frontend_console_print(format, args,ConsoleIoConsole);
244     va_end(args);
245 
246     return ret;
247 }
248 
249 int
error_printf(const char * format,...)250 error_printf(const char *format, ...)
251 {
252     va_list args;
253     int     ret;
254 
255     va_start(args, format);
256     ret = frontend_console_print(format, args, ConsoleIoError);
257     va_end(args);
258 
259     return ret;
260 }
261 
262 int
report_printf(const char * format,...)263 report_printf(const char *format, ...)
264 {
265     va_list args;
266     int     ret;
267 
268     va_start(args, format);
269     ret = frontend_console_print(format, args, ConsoleIoReport);
270     va_end(args);
271 
272     return ret;
273 }
274 
275 void
console_flush()276 console_flush()
277 {
278     frontend_console_flush(ConsoleIoConsole);
279 }
280 
281 void
error_flush()282 error_flush()
283 {
284     frontend_console_flush(ConsoleIoError);
285 }
286 
287 void
report_flush()288 report_flush()
289 {
290     frontend_console_flush(ConsoleIoReport);
291 }
292 
293 void
console_up(int n_lines)294 console_up(int n_lines)
295 {
296     if (!is_console_initialized(&Console_IO))
297         return; /* not initialized or already de-initialized */
298 #if defined(_WIN32)  &&  !defined(__CYGWIN__)
299     if (Console_IO.Console_file_type != FILE_TYPE_PIPE) {
300         COORD   Pos;
301         CONSOLE_SCREEN_BUFFER_INFO CSBI;
302 
303         console_flush();
304         GetConsoleScreenBufferInfo(Console_IO.Console_Handle, &CSBI);
305         Pos.Y = (SHORT)(CSBI.dwCursorPosition.Y - n_lines);
306         Pos.X = 0;
307         SetConsoleCursorPosition(Console_IO.Console_Handle, Pos);
308     }
309 #else
310     while (n_lines-- > 0)
311         fputs(Console_IO.str_up, Console_IO.Console_fp);
312     console_flush();
313 #endif
314 }
315 
316 int
console_getwidth()317 console_getwidth()
318 {
319     if (is_console_initialized(&Console_IO))
320         return Console_IO.disp_width;
321     return 80; /* default value */
322 }
323 
324 void
set_debug_file(const char * fn)325 set_debug_file(const char *fn)
326 {
327     if (is_console_initialized(&Console_IO)) {
328         if (Console_IO.Report_fp == NULL) {
329             Console_IO.Report_fp = lame_fopen(fn, "a");
330             if (Console_IO.Report_fp != NULL) {
331                 error_printf("writing debug info into: %s\n", fn);
332             }
333             else {
334                 error_printf("Error: can't open for debug info: %s\n", fn);
335             }
336         }
337     }
338 }
339 
340 /* end of console.c */
341