// // aegis - project change supervisor // Copyright (C) 1991-1993, 1995, 1998, 1999, 2002-2006, 2008 Peter Miller // // 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 3 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, see // . // #include #include #include output_indent::~output_indent() { trace(("output_indent::destructor()\n{\n")); // // Make sure all buffered data has been passed to our write_inner // method. // flush(); if (out_col) deeper->fputc('\n'); trace(("}\n")); } output_indent::output_indent(const output::pointer &a_deeper) : deeper(a_deeper), depth(0), in_col(0), out_col(0), continuation_line(0), pos(0) { trace(("output_indent::output_indent(this = %08lX, deeper = %08lX)\n", (long)this, (long)a_deeper.get())); } output_indent::ipointer output_indent::create(const output::pointer &a_deeper) { return ipointer(new output_indent(a_deeper)); } nstring output_indent::filename() const { return deeper->filename(); } long output_indent::ftell_inner() const { return pos; } // // Function Name: // indent_putchar // // Description: // The indent_putchar function is used to emity characters. // It keeps track of (){}[] pairs and indents between them. // Leading whitespace is suppressed and replaced with its own // idea of indenting. // // Preconditions: // none // // validation: // none // // Passed: // 'c' the character to emit. // void output_indent::write_inner(const void *p, size_t len) { const unsigned char *data = (unsigned char *)p; while (len > 0) { unsigned char c = *data++; --len; ++pos; switch (c) { case '\n': deeper->fputc('\n'); in_col = 0; out_col = 0; if (continuation_line == 1) continuation_line = 2; else continuation_line = 0; break; case ' ': if (out_col) ++in_col; break; case '\t': if (out_col) in_col = (in_col / INDENT + 1) * INDENT; break; case '\1': if (!out_col) break; if (in_col >= INDENT * (depth + 2)) in_col++; else in_col = INDENT * (depth + 2); break; case '}': case ')': case ']': --depth; // fall through default: if (!out_col && c != '#' && continuation_line != 2) in_col += INDENT * depth; if (!out_col) { // // Only emit tabs into the output if we are at // the start of a line. // for (;;) { if (out_col + 1 >= in_col) break; int x = ((out_col / INDENT) + 1) * INDENT; if (x > in_col) break; deeper->fputc('\t'); out_col = x; } } while (out_col < in_col) { deeper->fputc(' '); ++out_col; } if (c == '{' || c == '(' || c == '[') ++depth; deeper->fputc(c); ++in_col; out_col = in_col; continuation_line = (c == '\\'); break; } } } int output_indent::page_width() const { return deeper->page_width(); } int output_indent::page_length() const { return deeper->page_length(); } void output_indent::end_of_line_inner() { if (in_col) fputc('\n'); } const char * output_indent::type_name() const { return "indent"; } void output_indent::indent_more() { ++depth; } void output_indent::indent_less() { if (depth > 0) --depth; }