00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 #include <basix/port.hpp>
00014 #include <basix/system.hpp>
00015 
00017 
00018 namespace mmx {
00019 
00020 
00021 
00022 
00023 
00024 bool
00025 supports_color () {
00026   static bool terminal_supports_color=
00027     get_env ("TERM") == string ("xterm") ||
00028     get_env ("TERM") == string ("xterm-color") ||
00029     get_env ("TERM") == string ("xterm-256color");
00030   return terminal_supports_color && !texmacs_mode && color_mode;
00031 }
00032 
00033 
00034 
00035 
00036 
00037 class formatting_port_rep: public port_rep {
00038   port   p;
00039   string prefix;
00040   bool   need_indent;
00041   string indenter;
00042 
00043 public:
00044   syntactic expression () const {
00045     return syn ("formatting_port", flatten (p)); }
00046   bool is_output_port () {
00047     return mmx::is_output_port (p); }
00048   bool is_input_port () {
00049     return mmx::is_input_port (p); }
00050   bool error_flag () {
00051     return mmx::error_flag (p); }
00052   string error_message () {
00053     return mmx::error_message (p); }
00054   bool busy () {
00055     return mmx::busy (p); }
00056   nat can_write () {
00057     return mmx::can_write (p); }
00058   nat can_read () {
00059     return mmx::can_read (p); }
00060   void write (const char* s, nat n) {
00061     for (nat i=0; i<n; ) {
00062       nat start= i;
00063       while (i<n && s[i] != '\n') i++;
00064       if (i>start && need_indent) mmx::write (p, prefix);
00065       need_indent= (i<n);
00066       if (need_indent) i++;
00067       mmx::write (p, s+start, i-start);
00068     } }
00069   void read (char* s, nat n) {
00070     mmx::read (p, s, n); }
00071   void flush () {
00072     mmx::flush (p); }
00073   bool wait (int msecs) {
00074     return mmx::wait (p, msecs); }
00075   port component (const string& name) {
00076     if (name == "wrapped") return p;
00077     ERROR ("port not found"); }
00078 
00079   void format (const print_format& fm) {
00080     switch (fm) {
00081     case blank:
00082       indenter= "  ";
00083       break;
00084     case stroke:
00085       indenter= "| ";
00086       break;
00087     case indent:
00088       prefix << indenter;
00089       break;
00090     case unindent:
00091       inside (prefix) -> resize (max (N(prefix), N(indenter)) - N(indenter));
00092       break;
00093     case reset_indent:
00094       inside (prefix) -> resize (0);
00095       break;
00096     case cr:
00097       write ("\r", 1);
00098       break;
00099     case lf:
00100       write ("\n", 1);
00101       break;
00102     case hrule:
00103       write ("--------------------------------------------------------------------------------", 80);
00104       break;
00105     case flush_now:
00106       flush ();
00107       break;
00108 
00109     case black_foreground:
00110       if (supports_color ()) write ("\x1b[30m", 5);
00111       break;
00112     case red_foreground:
00113       if (supports_color ()) write ("\x1b[31m", 5);
00114       break;
00115     case green_foreground:
00116       if (supports_color ()) write ("\x1b[32m", 5);
00117       break;
00118     case yellow_foreground:
00119       if (supports_color ()) write ("\x1b[33m", 5);
00120       break;
00121     case blue_foreground:
00122       if (supports_color ()) write ("\x1b[34m", 5);
00123       break;
00124     case magenta_foreground:
00125       if (supports_color ()) write ("\x1b[35m", 5);
00126       break;
00127     case cyan_foreground:
00128       if (supports_color ()) write ("\x1b[36m", 5);
00129       break;
00130     case white_foreground:
00131       if (supports_color ()) write ("\x1b[37m", 5);
00132       break;
00133 
00134     case black_background:
00135       if (supports_color ()) write ("\x1b[40m", 5);
00136       break;
00137     case red_background:
00138       if (supports_color ()) write ("\x1b[41m", 5);
00139       break;
00140     case green_background:
00141       if (supports_color ()) write ("\x1b[42m", 5);
00142       break;
00143     case yellow_background:
00144       if (supports_color ()) write ("\x1b[43m", 5);
00145       break;
00146     case blue_background:
00147       if (supports_color ()) write ("\x1b[44m", 5);
00148       break;
00149     case magenta_background:
00150       if (supports_color ()) write ("\x1b[45m", 5);
00151       break;
00152     case cyan_background:
00153       if (supports_color ()) write ("\x1b[46m", 5);
00154       break;
00155     case white_background:
00156       if (supports_color ()) write ("\x1b[47m", 5);
00157       break;
00158 
00159     case bold:
00160       if (supports_color ()) write ("\x1b[1m", 4);
00161       break;
00162     case underline:
00163       if (supports_color ()) write ("\x1b[4m", 4);
00164       break;
00165     case blink:
00166       if (supports_color ()) write ("\x1b[5m", 4);
00167       break;
00168 
00169     case reset_attributes:
00170       if (supports_color ()) write ("\x1b[0m", 4);
00171       flush ();
00172       break;
00173     }
00174   }
00175 
00176 public:
00177   inline formatting_port_rep (const port& p2):
00178     p (p2), prefix (""), need_indent (true), indenter ("  ") {}
00179 };
00180 
00181 
00182 
00183 
00184 
00185 port
00186 formatting_port (const port& p) {
00187   return (port_rep*) new formatting_port_rep (p);
00188 }
00189 
00190 }