This is strindent.c in view mode; [Download] [Up]
//------------------------------------------------------------------------- // ^FILE: strindent.c - implement the strindent() function // // ^DESCRIPTION: // This file implements the function strmatch() which matches a // keyword (case insensitive) and the function strindent() which // prints a hanging, indented paragraph. // // On VMS systems - we also implement a replacement for "getenv()" // named "getsym()" to get the value of a VMS symbol. // // ^HISTORY: // 12/05/91 Brad Appleton <brad@ssd.csd.harris.com> Created //-^^----------------------------------------------------------------------- #include <iostream.h> #include <string.h> #include <ctype.h> #include "cmdline.h" // Need a portable version of tolower // // NOTE:: I would make this inline except that cfront refuses // to inline it because it is used twice in expressions // #define TO_LOWER(c) ((isupper(c)) ? tolower(c) : c) //------- // ^FUNCTION: strmatch - match a keyword // // ^SYNOPSIS: // static CmdLine::strmatch_t CmdLine::strmatch(src, attempt, len); // // ^PARAMETERS: // const char * src; // -- the actual keyword to match against // // const char * attempt; // -- the "candidate" that may or may not match the keyword // // unsigned len; // -- the number of character of "attempt" to consider (==0 if all // characters of "attempt" should be used). // // ^DESCRIPTION: // See if "attempt" matches "src" (either partially or completely) and // return the result. // // ^REQUIREMENTS: // None that havent been discusses in the PARAMETERS section. // // ^SIDE-EFFECTS: // None. // // ^RETURN-VALUE: // str_EXACT if "attempt" completely matches "src" // str_PARTIAL is "attempt" partially matches "src" // str_NONE otherwise // // ^ALGORITHM: // For each character (in order) of "attempt" to be considered // if attempt[i] != src[i] (case insensitive) return str_NONE // end-for // if we have exhausted "src" return str_EXACT, // else return str_PARTIAL //-^^---- CmdLine::strmatch_t CmdLine::strmatch(const char * src, const char * attempt, unsigned len) { unsigned i; if (src == attempt) return str_EXACT ; if ((src == NULL) || (attempt == NULL)) return str_NONE ; if ((! *src) && (! *attempt)) return str_EXACT ; if ((! *src) || (! *attempt)) return str_NONE ; for (i = 0 ; ((i < len) || (! len)) && (attempt[i] != '\0') ; i++) { if (TO_LOWER(src[i]) != TO_LOWER(attempt[i])) return str_NONE ; } return (src[i] == '\0') ? str_EXACT : str_PARTIAL ; } //-------------------------------------------------------------------------- // ^FUNCTION: strindent - print a hanging indented paragraph // // ^SYNOPSIS: // void CmdLine::strindent(os, maxcols, margin, title, indent, text) // // ^PARAMETERS: // ostream & os; // -- the stream to which output is sent // // unsigned maxcols; // -- the maximum width (in characters) of the output // // unsigned margin; // -- the number of spaces to use as the left margin // // char * title; // -- the paragraph title // // unsigned indent; // -- the distance between the title and the paragraph body // // char * text; // -- the body of the paragraph // // ^DESCRIPTION: // Strindent will print on os, a titled, indented paragraph as follows: // // <----------------------- maxcols ---------------------------> // <--- margin --><----- indent ----> // title This is the first sentence // of the paragraph. Etc ... // // ^REQUIREMENTS: // - maxcols and indent must be positive numbers with maxcols > indent. // - title should NOT contain any tabs or newlines. // // ^SIDE-EFFECTS: // Output is printed to os. // // ^RETURN-VALUE: // None. // // ^ALGORITHM: // Print the paragraph title and then print the text. // Lines are automatically adjusted so that each one starts in the // appropriate column. //-^^----------------------------------------------------------------------- void CmdLine::strindent(ostream & os, unsigned maxcols, unsigned margin, const char * title, unsigned indent, const char * text) { // If we were given non-sensical parameters then dont use them if (margin > maxcols) margin = 0; if ((indent + margin) >= maxcols) indent = 1; // print the title (left-justified) os.width(margin); os << "" ; long save_flags = os.flags(); os.setf(ios::left, ios::adjustfield); os.width(indent); os << ((title) ? title : ""); os.flags(save_flags); if (text == NULL) { os << endl ; return; } // If the title is too big, start the paragraph on a new line if (title && (::strlen(title) > indent)) { os << endl ; os.width(margin + indent); os << ""; } // Loop through the paragraph text witing to print until we absolutely // have to. // unsigned col = margin + indent + 1; unsigned index = 0 ; unsigned last_white = 0 ; const char * p = text ; while (p[index]) { switch (p[index]) { // If we have a space - just remember where it is case ' ' : last_white = index; ++col; ++index; break; // If we have a tab - remember where it is and assume it // will take up 8 spaces in the output. // case '\t' : last_white = index; col += 8; ++index; break; // If we have a form-feed, carriage-return, or newline, then // print what we have so far (including this character) and // start a new line. // case '\n' : case '\r' : case '\f' : os.write(p, index + 1); p += index + 1; col = margin + indent + 1; index = last_white = 0; if (*p) { os.width(margin + indent); os << ""; } break; default: ++col; ++index; break; } //switch // Are we forced to start a new line? if (col > maxcols) { // Yes - if possible, print upto the last whitespace character // and start the next line on a word-boundary if (last_white) { os.write(p, last_white); p += last_white; while (*p == ' ') ++p; } else { // No word boundary in sight - just split the line here! os.write(p, index); p += index; } os << endl ; // We just printed a newline - dont print another one right now while ((*p == '\n') || (*p == '\r') || (*p == '\f')) ++p; col = margin + indent + 1; index = last_white = 0; if (*p) { os.width(margin + indent); os << ""; } } else if (index && (! p[index])) { os << p << endl ; } } //while } #ifdef vms # include <descrip.h> # include <libdef.h> extern "C" { long lib$get_symbol(...); void exit(int); } //---------------------- // ^FUNCTION: getsym - retrieve the value of a VMS symbol // // ^SYNOPSIS: // const char * getsym(sym_name) // // ^PARAMETERS: // char * sym_name; // -- name of the symbol to retrieve // // ^DESCRIPTION: // Get_symbol will lookup the named symbol and return its value // as a string. // // ^REQUIREMENTS: // sym_name should correspond to the name of a pre-defined symbol. // // ^SIDE-EFFECTS: // None. NO storage is allocated for the symbol-value and it will // be overwritten by the next call to this function. // // ^RETURN-VALUE: // NULL if the symbol is not found, otherwise it returns a pointer // to a static buffer containing the contents of the symbol value. // You MUST be finished using this buffer before another call to // get_symbol is made. // // ^ACKNOWLEDGEMENTS: // Thanx to Jim Barbour for writing most of this code. --BDA // // ^ALGORITHM: // Trivial - just use the LIB$GET_SYMBOL system service. //-^^------------------- const char * getsym(const char * sym_name) { static char sym_value[256]; unsigned long stat; unsigned short buflen; $DESCRIPTOR(sym_name_d, sym_name); $DESCRIPTOR(sym_value_d, sym_value); sym_value_d.dsc$w_length = sizeof(sym_value); sym_name_d.dsc$w_length = ::strlen(sym_name); stat = lib$get_symbol(&sym_name_d, &sym_value_d, &buflen, (void *)0); if (stat == LIB$_NOSUCHSYM) { return NULL; } else if (! (stat & 1)) { ::exit(stat); } sym_value[buflen] = '\0'; return sym_value; } #endif /* vms */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.