From: <ny...@us...> - 2007-01-03 10:49:34
|
Revision: 231 http://svn.sourceforge.net/pmplib/?rev=231&view=rev Author: nyaochi Date: 2007-01-03 02:49:31 -0800 (Wed, 03 Jan 2007) Log Message: ----------- - Moved Martin's TTY management code to console_posix.c (untested). - Implemented the similar console routine for Win32 (console_win32.c). Modified Paths: -------------- trunk/pmplib/frontend/easypmp/cui/easypmp_cui.vcproj trunk/pmplib/frontend/easypmp/cui/util.c Added Paths: ----------- trunk/pmplib/frontend/easypmp/cui/console.h trunk/pmplib/frontend/easypmp/cui/console_posix.c trunk/pmplib/frontend/easypmp/cui/console_win32.c Added: trunk/pmplib/frontend/easypmp/cui/console.h =================================================================== --- trunk/pmplib/frontend/easypmp/cui/console.h (rev 0) +++ trunk/pmplib/frontend/easypmp/cui/console.h 2007-01-03 10:49:31 UTC (rev 231) @@ -0,0 +1,39 @@ +/* + * Console manupulator. + * + * Copyright (c) 2006 Nyaochi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit + * http://www.gnu.org/copyleft/gpl.html . + * + */ + +/* $Id$ */ + +#ifndef __CONSOLE_H__ +#define __CONSOLE_H__ + +/** + * \addtogroup cui + * @{ + */ + +int console_init(); +int console_clearln(FILE *fp); +int console_println(FILE *fp, const ucs2char_t* line, int min_width); + +/** @} */ + +#endif/*__CONSOLE_H__*/ Property changes on: trunk/pmplib/frontend/easypmp/cui/console.h ___________________________________________________________________ Name: svn:keywords + Id Added: trunk/pmplib/frontend/easypmp/cui/console_posix.c =================================================================== --- trunk/pmplib/frontend/easypmp/cui/console_posix.c (rev 0) +++ trunk/pmplib/frontend/easypmp/cui/console_posix.c 2007-01-03 10:49:31 UTC (rev 231) @@ -0,0 +1,201 @@ +/* + * Miscellaneous utilities. + * + * Copyright (c) 2005-2006 Nyaochi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit + * http://www.gnu.org/copyleft/gpl.html . + * + */ + +/* $Id$ */ + +/** + * @file + * Utility functions for the easypmp command line program (mostly + * display related). + * + * @addtogroup cui + * @{ + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif/*HAVE_CONFIG_H*/ +#ifdef HAVE_STRING_H +#include <string.h> +#endif/*HAVE_STRING_H*/ + +#include <os.h> +#include <stdio.h> +#include <stdlib.h> +#include <ucs2char.h> + +#include "console.h" + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#if CAN_GET_WIN_SIZE +#include <sys/ioctl.h> +#include <signal.h> +#endif/*CAN_GET_WIN_SIZE*/ + +#include "util.h" + +#if CAN_GET_WIN_SIZE +/** + * The number of characters that can be printed on a single line, + * without causing a line wrap. Since the right-most column is + * required for the cursor, this is one less than the actual terminal + * width. + * + * Defaults to 79 on systems where we can't tell the width of the + * terminal. + */ +static volatile unsigned short int window_width; +#else +static const unsigned short int window_width = 79; +#endif + +/** + * The minimum width of the terminal we're willing to entertain. If + * the terminal gets narrower than this width, we treat it as this + * width. Note that it must be at least 2 to allow for one character + * and the cursor. +*/ +static const int min_term_width = 6; + + +#define POSSIBLE_TTYS 2 +/** + * Flags to indicate whether stdin, stdout, and stderr are attached to + * a terminal. These are used to determine whether we should check + * the width of some progress lines before printing them. Initialised + * in display_init. + */ +static int fd_is_tty[POSSIBLE_TTYS+1]; + +#if CAN_GET_WIN_SIZE + +/** + * Handler for the "terminal window changed size" signal. + * + * @param unused + */ +void window_size_changed(int unused) +{ + static struct winsize wsize; + if (ioctl(1, TIOCGWINSZ, &wsize) != -1) { + if (wsize.ws_col > min_term_width) { + window_width = wsize.ws_col - 1; + } else { + window_width = min_term_width; + } + } +} + +#endif/*CAN_GET_WIN_SIZE*/ + +/** + * Determines whether stdin, stdout and stderr are associated with a + * TTY, and update fd_is_tty accordingly. Also sets up + * window_size_changed as a signal handler. + */ +void display_init() +{ +#ifdef HAVE_TTY + int i; + for(i = 0; i <= POSSIBLE_TTYS; ++i) + fd_is_tty[i] = isatty(i); + +#if CAN_GET_WIN_SIZE + signal(SIGWINCH,window_size_changed); + window_size_changed(0); +#endif/*CAN_GET_WIN_SIZE*/ +#endif/*HAVE_TTY*/ +} + +/** + * Deletes all text on the current line by overwriting it with spaces. + * + * A 'blank line' is written to a given file pointer, @p fp. That is, + * a number of spaces equal to the current window width is written. + * This is followed by a carriage return character, to return the + * cursor to the start of the line. +*/ +void clear_line(FILE *fp) +{ + /* fmt needs 4 chars (%, -, s, \r) + + room for window_width as string (max. 65535) + + null terminator */ + char fmt[10]; + sprintf(fmt, "%%-%us\r", window_width); + fprintf(fp, fmt, ""); +} + +/** + * Displays a UCS-2 string truncated for the terminal width. + * + * Displays as much of a UCS-2 encoded string as will fit on a single + * line in the terminal, and returning the cursor to the start of the + * line. If the terminal is less that the given minimum width, that + * minimum number of characters is displayed anyway, even if it means + * the text will wrap onto the next line. + * + * If @p fp isn't associated with a terminal, just print the whole line. + * + * @param fp FILE* to print on + * @param line the UCS-2 encoded string to display + * @param min_width minimum number of characters to print + */ +void display_line(FILE *fp, const ucs2char_t* const line, + unsigned int min_width) +{ + unsigned int length = ucs2len(line); + const ucs2char_t* line_to_print; + + int writing_to_tty; + /* Check if writing to a terminal. If so, clear the current line. */ + int fd = fileno(fp); + if (0 < fd && fd <= POSSIBLE_TTYS && fd_is_tty[fd]) { + clear_line(fp); + writing_to_tty = 1; + } else { + writing_to_tty = 0; + } + + if(!writing_to_tty) { + /* Write the whole line to the file, add \n. */ + fprints(fp, "%s\r\n", line); + } else if (length <= window_width) { + /* There's enough room to show the whole line. */ + fprints(fp, "%s\r", line); + } + else { + /* Length of the longest string we might display: */ + const int max_trunc_length = MAX(window_width,min_width); + + /* Length of string we actually will display: */ + const size_t trunc_length = MIN(max_trunc_length, length); + + ucs2char_t *truncated_line = ucs2calloc(sizeof(ucs2char_t) * (trunc_length+1)); + ucs2ncpy(truncated_line, line, trunc_length); + fprints(fp, "%s\r", truncated_line); + } +} + + +/** @} */ Property changes on: trunk/pmplib/frontend/easypmp/cui/console_posix.c ___________________________________________________________________ Name: svn:keywords + Id Added: trunk/pmplib/frontend/easypmp/cui/console_win32.c =================================================================== --- trunk/pmplib/frontend/easypmp/cui/console_win32.c (rev 0) +++ trunk/pmplib/frontend/easypmp/cui/console_win32.c 2007-01-03 10:49:31 UTC (rev 231) @@ -0,0 +1,109 @@ +/* + * Console manupulator for Win32 API. + * + * Copyright (c) 2006 Nyaochi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit + * http://www.gnu.org/copyleft/gpl.html . + * + */ + +/* $Id:$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif/*HAVE_CONFIG_H*/ + +#include <os.h> +#include <io.h> +#include <stdio.h> +#include <stdlib.h> +#include <ucs2char.h> + +#include <windows.h> + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +static HANDLE get_handle(FILE *fp) +{ + return (HANDLE)_get_osfhandle(_fileno(fp)); +} + +int console_init() +{ + return 0; +} + +int console_clearln(FILE *fp) +{ + HANDLE hOutput = (HANDLE)_get_osfhandle(_fileno(fp)); + CONSOLE_SCREEN_BUFFER_INFO csbi; + + memset(&csbi, 0, sizeof(csbi)); + if (GetConsoleScreenBufferInfo(hOutput, &csbi)) { + /* The output is a console buffer. */ + DWORD num_written = 0; + csbi.dwCursorPosition.X = csbi.srWindow.Left; + FillConsoleOutputCharacterA( + hOutput, + ' ', + csbi.srWindow.Right - csbi.srWindow.Left + 1, + csbi.dwCursorPosition, + &num_written + ); + SetConsoleCursorPosition(hOutput, csbi.dwCursorPosition); + return 0; + } else { + /* Does nothing for non-console buffer (e.g., redirected file) */ + return 1; + } +} + +int console_println(FILE *fp, const ucs2char_t* line, int min_width) +{ + const int margin = 5; + HANDLE hOutput = (HANDLE)_get_osfhandle(_fileno(fp)); + CONSOLE_SCREEN_BUFFER_INFO csbi; + + memset(&csbi, 0, sizeof(csbi)); + if (GetConsoleScreenBufferInfo(hOutput, &csbi)) { + int x = 0, width = 0; + const ucs2char_t* p = line; + + while (*p) { + memset(&csbi, 0, sizeof(csbi)); + GetConsoleScreenBufferInfo(hOutput, &csbi); + + x = (int)csbi.dwCursorPosition.X; + width = (int)(csbi.srWindow.Right - csbi.srWindow.Left) + 1; + if (width <= x + margin) { + int ndotts = MIN(3, width - x); + while (ndotts-- > 0) fputc('.', fp); + break; + } else { + fputwc((wchar_t)*p, fp); + } + p++; + } + fputc('\r', fp); + return (int)(p - line); + } else { + fprintf(fp, "%S\n", line); + return ucs2len(line); + } +} + + +/** @} */ Property changes on: trunk/pmplib/frontend/easypmp/cui/console_win32.c ___________________________________________________________________ Name: svn:keywords + Id Modified: trunk/pmplib/frontend/easypmp/cui/easypmp_cui.vcproj =================================================================== --- trunk/pmplib/frontend/easypmp/cui/easypmp_cui.vcproj 2006-12-31 07:38:06 UTC (rev 230) +++ trunk/pmplib/frontend/easypmp/cui/easypmp_cui.vcproj 2007-01-03 10:49:31 UTC (rev 231) @@ -180,6 +180,10 @@ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > <File + RelativePath=".\console_win32.c" + > + </File> + <File RelativePath=".\device.c" > </File> @@ -210,6 +214,10 @@ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" > <File + RelativePath=".\console.h" + > + </File> + <File RelativePath=".\getopt.h" > </File> Modified: trunk/pmplib/frontend/easypmp/cui/util.c =================================================================== --- trunk/pmplib/frontend/easypmp/cui/util.c 2006-12-31 07:38:06 UTC (rev 230) +++ trunk/pmplib/frontend/easypmp/cui/util.c 2007-01-03 10:49:31 UTC (rev 231) @@ -43,159 +43,9 @@ #include <stdlib.h> #include <ucs2char.h> -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#include "console.h" -#if CAN_GET_WIN_SIZE -#include <sys/ioctl.h> -#include <signal.h> -#endif/*CAN_GET_WIN_SIZE*/ - -#include "util.h" - -#if CAN_GET_WIN_SIZE /** - * The number of characters that can be printed on a single line, - * without causing a line wrap. Since the right-most column is - * required for the cursor, this is one less than the actual terminal - * width. - * - * Defaults to 79 on systems where we can't tell the width of the - * terminal. - */ -static volatile unsigned short int window_width; -#else -static const unsigned short int window_width = 79; -#endif - -/** - * The minimum width of the terminal we're willing to entertain. If - * the terminal gets narrower than this width, we treat it as this - * width. Note that it must be at least 2 to allow for one character - * and the cursor. -*/ -static const int min_term_width = 6; - - -#define POSSIBLE_TTYS 2 -/** - * Flags to indicate whether stdin, stdout, and stderr are attached to - * a terminal. These are used to determine whether we should check - * the width of some progress lines before printing them. Initialised - * in display_init. - */ -static int fd_is_tty[POSSIBLE_TTYS+1]; - -#if CAN_GET_WIN_SIZE - -/** - * Handler for the "terminal window changed size" signal. - * - * @param unused - */ -void window_size_changed(int unused) -{ - static struct winsize wsize; - if (ioctl(1, TIOCGWINSZ, &wsize) != -1) { - if (wsize.ws_col > min_term_width) { - window_width = wsize.ws_col - 1; - } else { - window_width = min_term_width; - } - } -} - -#endif/*CAN_GET_WIN_SIZE*/ - -/** - * Determines whether stdin, stdout and stderr are associated with a - * TTY, and update fd_is_tty accordingly. Also sets up - * window_size_changed as a signal handler. - */ -void display_init() -{ -#ifdef HAVE_TTY - int i; - for(i = 0; i <= POSSIBLE_TTYS; ++i) - fd_is_tty[i] = isatty(i); - -#if CAN_GET_WIN_SIZE - signal(SIGWINCH,window_size_changed); - window_size_changed(0); -#endif/*CAN_GET_WIN_SIZE*/ -#endif/*HAVE_TTY*/ -} - -/** - * Deletes all text on the current line by overwriting it with spaces. - * - * A 'blank line' is written to a given file pointer, @p fp. That is, - * a number of spaces equal to the current window width is written. - * This is followed by a carriage return character, to return the - * cursor to the start of the line. -*/ -void clear_line(FILE *fp) -{ - /* fmt needs 4 chars (%, -, s, \r) + - room for window_width as string (max. 65535) + - null terminator */ - char fmt[10]; - sprintf(fmt, "%%-%us\r", window_width); - fprintf(fp, fmt, ""); -} - -/** - * Displays a UCS-2 string truncated for the terminal width. - * - * Displays as much of a UCS-2 encoded string as will fit on a single - * line in the terminal, and returning the cursor to the start of the - * line. If the terminal is less that the given minimum width, that - * minimum number of characters is displayed anyway, even if it means - * the text will wrap onto the next line. - * - * If @p fp isn't associated with a terminal, just print the whole line. - * - * @param fp FILE* to print on - * @param line the UCS-2 encoded string to display - * @param min_width minimum number of characters to print - */ -void display_line(FILE *fp, const ucs2char_t* const line, - unsigned int min_width) -{ - unsigned int length = ucs2len(line); - const ucs2char_t* line_to_print; - - int writing_to_tty; - /* Check if writing to a terminal. If so, clear the current line. */ - int fd = fileno(fp); - if (0 < fd && fd <= POSSIBLE_TTYS && fd_is_tty[fd]) { - clear_line(fp); - writing_to_tty = 1; - } else { - writing_to_tty = 0; - } - - if(!writing_to_tty) { - /* Write the whole line to the file, add \n. */ - fprints(fp, "%s\r\n", line); - } else if (length <= window_width) { - /* There's enough room to show the whole line. */ - fprints(fp, "%s\r", line); - } - else { - /* Length of the longest string we might display: */ - const int max_trunc_length = MAX(window_width,min_width); - - /* Length of string we actually will display: */ - const size_t trunc_length = MIN(max_trunc_length, length); - - ucs2char_t *truncated_line = ucs2calloc(sizeof(ucs2char_t) * (trunc_length+1)); - ucs2ncpy(truncated_line, line, trunc_length); - fprints(fp, "%s\r", truncated_line); - } -} - -/** * Generic display method for progress messages consisting of a * number and a string. * @@ -215,24 +65,9 @@ display_line is used to truncate the line in this way. */ - - // Numeric part, plus associated punctuation - const int prefix_length = 16; - char *fmt = alloca(sizeof(char) * prefix_length + 1); - - ucs2char_t *line = alloca(sizeof(ucs2char_t) * (ucs2len(msg) + prefix_length + 1)); - ucs2char_t *fmt_ucs2; - - // Build the numeric part... - sprintf(fmt, " %u: ", n); - fmt_ucs2 = mbsdupucs2(fmt); - if (fmt_ucs2) { - ucs2cpy(line, fmt_ucs2); - // ... and append the message. - ucs2cat(line, msg); - display_line(fp, line, strlen(fmt)); - ucs2free(fmt_ucs2); - } + console_clearln(fp); + fprintf(fp, " %u: ", n); + console_println(fp, msg, 0); return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |