stdio.cxx
Go to the documentation of this file.
00001 /** 00002 * @file stdio.cxx 00003 * @brief Standard I/O functions. 00004 * 00005 * Copyright (c) 2012 University of Pennsylvania. All rights reserved.<br /> 00006 * See https://www.cbica.upenn.edu/sbia/software/license.html or COPYING file. 00007 * 00008 * Contact: SBIA Group <sbia-software at uphs.upenn.edu> 00009 */ 00010 00011 #include <basis/config.h> // WINDOWS macro 00012 #include <basis/assert.h> // assert() 00013 00014 #include <stdlib.h> // getenv() 00015 00016 #if WINDOWS 00017 # include <windows.h> // GetConsoleScreenBufferInfo() 00018 #else 00019 # include <unistd.h> // STDOUT_FILENO 00020 # include <sys/ioctl.h> // ioctl() 00021 #endif 00022 00023 #include <basis/stdio.h> 00024 00025 00026 // acceptable in .cxx file 00027 using namespace std; 00028 00029 00030 namespace basis { 00031 00032 00033 // --------------------------------------------------------------------------- 00034 void get_terminal_size(int& lines, int& columns) 00035 { 00036 lines = 0; 00037 columns = 0; 00038 #if WINDOWS 00039 CONSOLE_SCREEN_BUFFER_INFO csbi; 00040 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { 00041 columns = csbi.dwSize.X; 00042 lines = csbi.dwSize.Y; 00043 } 00044 #else 00045 struct winsize w; 00046 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) { 00047 columns = w.ws_col; 00048 lines = w.ws_row; 00049 } 00050 #endif 00051 if (columns == 0) { 00052 const char* COLUMNS = getenv("COLUMNS"); 00053 if (COLUMNS) columns = atoi(COLUMNS); 00054 } 00055 if (lines == 0) { 00056 const char* LINES = getenv("LINES"); 00057 if (LINES) columns = atoi(LINES); 00058 } 00059 } 00060 00061 // --------------------------------------------------------------------------- 00062 int get_terminal_lines() 00063 { 00064 int lines, columns; 00065 get_terminal_size(lines, columns); 00066 return lines; 00067 } 00068 00069 // --------------------------------------------------------------------------- 00070 int get_terminal_columns() 00071 { 00072 int lines, columns; 00073 get_terminal_size(lines, columns); 00074 return columns; 00075 } 00076 00077 // --------------------------------------------------------------------------- 00078 ostream& print_wrapped(ostream& os, 00079 const string& text, 00080 int width, 00081 int indent, 00082 int offset) 00083 { 00084 assert(indent + offset < width); // such that allowed_length > 0 00085 00086 int text_length = static_cast<int>(text.length()); 00087 int allowed_length = width - indent; 00088 int start = 0; 00089 00090 // Note: Despite of the TCLAP::StdOutput::spacePrint() implementation, 00091 // the following while loop is always performed even if the given 00092 // text seems to fit on one line. Reason is that the text can 00093 // include newline characters itself. In this case, we still need 00094 // to take care of the proper indentation of the consecutive lines. 00095 00096 while (start < text_length) { 00097 // determine length of next line to be printed 00098 int line_length = min<int>(text_length - start, allowed_length); 00099 if (line_length == allowed_length) { 00100 while (line_length >= 0 && 00101 text[start + line_length] != ' ' && 00102 text[start + line_length] != ',' && 00103 text[start + line_length] != '|' ) { 00104 line_length--; 00105 } 00106 } 00107 if (line_length <= 0) line_length = allowed_length; 00108 // truncate line at already present newline (including the newline) 00109 for (int i = 0; i < line_length; i++) { 00110 if (text[start + i] == '\n') line_length = i + 1; 00111 } 00112 // print the line and add a newline 00113 for (int i = 0; i < indent; i++ ) os << " "; 00114 os << text.substr(start, line_length) << endl; 00115 // adjust indent for lines after the first one 00116 if (start == 0) { 00117 indent += offset; 00118 allowed_length -= offset; 00119 } 00120 // next line 00121 start += line_length; 00122 // skip space characters so next line does not start with 00123 // a further indentation besides the one specified by the indent 00124 while (text[start] == ' ' && start < text_length) start++; 00125 } 00126 00127 return os; 00128 } 00129 00130 00131 } // namespace basis