// // aegis - project change supervisor // Copyright (C) 1994, 2003-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 // for assert #include #include #include #include #include #include #include #include #include #include #include #include #include rpt_func_columns::~rpt_func_columns() { trace(("%s\n", __PRETTY_FUNCTION__)); } rpt_func_columns::rpt_func_columns() { trace(("%s\n", __PRETTY_FUNCTION__)); } rpt_func::pointer rpt_func_columns::create() { trace(("%s\n", __PRETTY_FUNCTION__)); return pointer(new rpt_func_columns()); } const char * rpt_func_columns::name() const { return "columns"; } bool rpt_func_columns::optimizable() const { return false; } bool rpt_func_columns::verify(const rpt_expr::pointer &ep) const { trace(("%s\n", __PRETTY_FUNCTION__)); return (ep->get_nchildren() > 0); } static long extract_integer(const rpt_value::pointer &vp, int minimum_result) { trace(("%s\n", __PRETTY_FUNCTION__)); if (!vp) return -1; if (dynamic_cast(vp.get())) return -1; rpt_value::pointer vp3 = rpt_value::integerize(vp); rpt_value_integer *ivp = dynamic_cast(vp3.get()); if (ivp) { long result = ivp->query(); if (result < minimum_result) { trace(("%ld < %d ==> -1\n", result, minimum_result)); return -1; } trace(("==> %ld\n", result)); return result; } // // If all else fails, cry. // trace(("not an int => -1\n")); return -1; } static nstring extract_string(const rpt_value::pointer &vp) { trace(("%s\n", __PRETTY_FUNCTION__)); if (!vp) return ""; rpt_value::pointer vp3 = rpt_value::stringize(vp); rpt_value_string *svp = dynamic_cast(vp3.get()); if (svp) return svp->query(); return ""; } rpt_value::pointer rpt_func_columns::run(const rpt_expr::pointer &, size_t argc, rpt_value::pointer *argv) const { trace(("%s\n", __PRETTY_FUNCTION__)); // // Nuke the old columns. // while (rpt_func_print__ncolumns > 0) { trace(("mark\n")); --rpt_func_print__ncolumns; size_t j = rpt_func_print__ncolumns; rpt_func_print__column[j].reset(); } // // Allocate more space if we need it. // if (argc >= rpt_func_print__ncolumns_max) { trace(("argc = %d\n", (int)argc)); size_t new_rpt_func_print__ncolumns_max = rpt_func_print__ncolumns_max * 2 + 8; while (argc >= new_rpt_func_print__ncolumns_max) { new_rpt_func_print__ncolumns_max = new_rpt_func_print__ncolumns_max * 2 + 8; } trace(("new max = %d\n", (int)new_rpt_func_print__ncolumns_max)); output::pointer *new_rpt_func_print__column = new output::pointer [new_rpt_func_print__ncolumns_max]; size_t k = 0; for (; k < rpt_func_print__ncolumns_max; ++k) new_rpt_func_print__column[k] = rpt_func_print__column[k]; delete [] rpt_func_print__column; rpt_func_print__column = new_rpt_func_print__column; rpt_func_print__ncolumns_max = new_rpt_func_print__ncolumns_max; } // // Create each of the columns. // trace(("create each of the columns\n")); assert(rpt_func_print__colp); int right = 0; int padding_prev = 0; for (size_t j = 0; j < argc; ++j) { trace(("j = %d of %d\n", (int)j, (int)argc)); rpt_value::pointer vp = argv[j]; nstring nname; int left = -1; int padding = -1; int rightm = -1; int width = -1; rpt_value_struct *rvs = dynamic_cast(vp.get()); if (rvs) { trace(("{ struct }\n")); rpt_value::pointer vp2 = rvs->lookup("left"); left = extract_integer(vp2, 0); trace(("left = %d\n", left)); vp2 = rvs->lookup("name"); nname = extract_string(vp2); vp2 = rvs->lookup("padding"); padding = extract_integer(vp2, 0); trace(("padding = %d\n", padding)); vp2 = rvs->lookup("right"); rightm = extract_integer(vp2, 0); trace(("rightm = %d\n", rightm)); vp2 = rvs->lookup("width"); width = extract_integer(vp2, 1); trace(("width = %d\n", width)); } else { vp = rpt_value::stringize(vp); nname = extract_string(vp); } // // padding defaults to 1 // except on the left margin // if (padding < 0) padding = (right != 0); trace(("padding = %d\n", padding)); // // left defaults to the right of the previous column // // padding applies on the left and on the right // if (left < 0) { if (rightm > 0 && width > 0 && rightm >= right + width) { trace(("left = rightm - width\n")); left = rightm - width; } else if (right) { if (padding > padding_prev) { trace(("left = right + padding;\n")); left = right + padding; } else { trace(("left = right + padding_prev;\n")); left = right + padding_prev; } } else { trace(("left = edge;\n")); left = 0; } } trace(("left = %d\n", left)); // // the width defaults to 7 // (default padding + default width == 8, so tabs work) // if (width < 0) { if (rightm > left) width = rightm - left; else width = 7; } trace(("width = %d\n", width)); if (rightm == 0) right = rightm; else right = left + width; trace(("right = %d\n", right)); // // create the column and set its heading // rpt_func_print__column[j] = rpt_func_print__colp->create(left, right, nname.c_str()); // // setup for next column // padding_prev = padding; trace(("mark\n")); } rpt_func_print__ncolumns = argc; // // done // trace(("done\n")); return rpt_value_null::create(); }