1 //////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (C) 2009-2021 The Octave Project Developers 4 // 5 // See the file COPYRIGHT.md in the top-level directory of this 6 // distribution or <https://octave.org/copyright/>. 7 // 8 // This file is part of Octave. 9 // 10 // Octave is free software: you can redistribute it and/or modify it 11 // under the terms of the GNU General Public License as published by 12 // the Free Software Foundation, either version 3 of the License, or 13 // (at your option) any later version. 14 // 15 // Octave is distributed in the hope that it will be useful, but 16 // WITHOUT ANY WARRANTY; without even the implied warranty of 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 // GNU General Public License for more details. 19 // 20 // You should have received a copy of the GNU General Public License 21 // along with Octave; see the file COPYING. If not, see 22 // <https://www.gnu.org/licenses/>. 23 // 24 //////////////////////////////////////////////////////////////////////// 25 26 #if ! defined (octave_text_engine_h) 27 #define octave_text_engine_h 1 28 29 #include "octave-config.h" 30 31 #include <memory> 32 #include <string> 33 34 #include "base-list.h" 35 #include "caseless-str.h" 36 #include "dMatrix.h" 37 38 namespace octave 39 { 40 class text_element; 41 class text_element_string; 42 class text_element_symbol; 43 class text_element_list; 44 class text_element_subscript; 45 class text_element_superscript; 46 class text_element_combined; 47 class text_element_fontname; 48 class text_element_fontsize; 49 class text_element_fontstyle; 50 class text_element_color; 51 52 class text_processor; 53 54 class 55 OCTINTERP_API 56 text_element 57 { 58 public: text_element(void)59 text_element (void) { } 60 61 virtual ~text_element (void) = default; 62 63 virtual void accept (text_processor& p) = 0; 64 65 private: 66 text_element (const text_element&); 67 }; 68 69 class 70 OCTINTERP_API 71 text_element_string : public text_element 72 { 73 public: 74 text_element_string (const std::string& s = "") text_element()75 : text_element (), str (s) { } 76 77 ~text_element_string (void) = default; 78 string_value(void)79 std::string string_value (void) const { return str; } 80 81 void accept (text_processor& p); 82 83 private: 84 std::string str; 85 86 private: 87 text_element_string (const text_element_string &); 88 }; 89 90 class 91 OCTINTERP_API 92 text_element_symbol : public text_element 93 { 94 public: 95 enum { invalid_code = 0xFFFFFFFFU }; 96 97 public: text_element_symbol(int sym)98 text_element_symbol (int sym) 99 : text_element (), symbol (sym) { } 100 101 ~text_element_symbol (void) = default; 102 get_symbol(void)103 int get_symbol (void) const { return symbol; } 104 105 uint32_t get_symbol_code (void) const; 106 107 void accept (text_processor& p); 108 109 private: 110 int symbol; 111 }; 112 113 class 114 OCTINTERP_API 115 text_element_list 116 : public text_element, public base_list<text_element *> 117 { 118 public: text_element_list(void)119 text_element_list (void) 120 : text_element (), base_list<text_element*> () { } 121 text_element_list(text_element * e)122 text_element_list (text_element *e) 123 : text_element (), base_list<text_element*> () 124 { 125 push_back (e); 126 } 127 ~text_element_list(void)128 ~text_element_list (void) 129 { 130 while (! empty ()) 131 { 132 auto it = begin (); 133 delete (*it); 134 erase (it); 135 } 136 } 137 138 void accept (text_processor& p); 139 }; 140 141 class 142 OCTINTERP_API 143 text_element_subscript : public text_element 144 { 145 public: text_element_subscript(text_element * e)146 text_element_subscript (text_element *e) 147 : text_element (), elem (e) { } 148 text_element_subscript(char c)149 text_element_subscript (char c) 150 : text_element () 151 { elem = new text_element_string (std::string (1, c)); } 152 ~text_element_subscript(void)153 ~text_element_subscript (void) 154 { delete elem; } 155 156 void accept (text_processor& p); 157 get_element(void)158 text_element * get_element (void) { return elem; } 159 160 private: 161 text_element *elem; 162 163 private: 164 text_element_subscript (void); 165 }; 166 167 class 168 OCTINTERP_API 169 text_element_superscript : public text_element 170 { 171 public: text_element_superscript(text_element * e)172 text_element_superscript (text_element *e) 173 : text_element (), elem (e) { } 174 text_element_superscript(char c)175 text_element_superscript (char c) 176 : text_element () 177 { elem = new text_element_string (std::string (1, c)); } 178 ~text_element_superscript(void)179 ~text_element_superscript (void) 180 { delete elem; } 181 182 void accept (text_processor& p); 183 get_element(void)184 text_element * get_element (void) { return elem; } 185 186 private: 187 text_element *elem; 188 189 private: 190 text_element_superscript (void); 191 }; 192 193 class 194 OCTINTERP_API 195 text_element_combined : public text_element_list 196 { 197 public: text_element_combined(text_element * e)198 text_element_combined (text_element *e) 199 : text_element_list (e) { } 200 text_element_combined(text_element * e1,text_element * e2)201 text_element_combined (text_element *e1, text_element *e2) 202 : text_element_list(e1) 203 { push_back (e2); } 204 205 void accept (text_processor& p); 206 }; 207 208 class 209 OCTINTERP_API 210 text_element_fontstyle : public text_element 211 { 212 public: 213 enum fontstyle 214 { 215 normal, 216 bold, 217 italic, 218 oblique 219 }; 220 text_element_fontstyle(fontstyle st)221 text_element_fontstyle (fontstyle st) 222 : text_element (), style (st) { } 223 224 ~text_element_fontstyle (void) = default; 225 get_fontstyle(void)226 fontstyle get_fontstyle (void) const { return style; } 227 228 void accept (text_processor& p); 229 230 private: 231 fontstyle style; 232 233 private: 234 text_element_fontstyle (void); 235 }; 236 237 class 238 OCTINTERP_API 239 text_element_fontname : public text_element 240 { 241 public: text_element_fontname(const std::string & fname)242 text_element_fontname (const std::string& fname) 243 : text_element (), name (fname) { } 244 245 ~text_element_fontname (void) = default; 246 get_fontname(void)247 const std::string& get_fontname (void) const { return name; } 248 249 void accept (text_processor& p); 250 251 private: 252 std::string name; 253 254 private: 255 text_element_fontname (void); 256 }; 257 258 class 259 OCTINTERP_API 260 text_element_fontsize : public text_element 261 { 262 public: text_element_fontsize(double fsize)263 text_element_fontsize (double fsize) 264 : text_element (), size (fsize) { } 265 266 ~text_element_fontsize (void) = default; 267 get_fontsize(void)268 double get_fontsize (void) const { return size; } 269 270 void accept (text_processor& p); 271 272 private: 273 double size; 274 275 private: 276 text_element_fontsize (void); 277 }; 278 279 class 280 OCTINTERP_API 281 text_element_color : public text_element 282 { 283 public: text_element_color(double r,double g,double b)284 text_element_color (double r, double g, double b) 285 : text_element (), rgb (1, 3, 0.0) 286 { 287 rgb(0) = r; 288 rgb(1) = g; 289 rgb(2) = b; 290 } 291 text_element_color(const std::string & cname)292 text_element_color (const std::string& cname) 293 : text_element (), rgb (1, 3, 0.0) 294 { 295 #define ASSIGN_COLOR(r,g,b) { rgb(0) = r; rgb(1) = g; rgb(2) = b; } 296 if (cname == "red") ASSIGN_COLOR(1, 0, 0) 297 else if (cname == "green") ASSIGN_COLOR(0, 1, 0) 298 else if (cname == "yellow") ASSIGN_COLOR(1, 1, 0) 299 else if (cname == "magenta") ASSIGN_COLOR(1, 0, 1) 300 else if (cname == "blue") ASSIGN_COLOR(0, 0, 1) 301 else if (cname == "black") ASSIGN_COLOR(0, 0, 0) 302 else if (cname == "white") ASSIGN_COLOR(1, 1, 1) 303 else if (cname == "gray") ASSIGN_COLOR(.5, .5, .5) 304 else if (cname == "darkGreen") ASSIGN_COLOR(0, .5, 0) 305 else if (cname == "orange") ASSIGN_COLOR(1, .65, 0) 306 else if (cname == "lightBlue") ASSIGN_COLOR(0.68, .85, .9) 307 #undef ASSIGN_COLOR 308 } 309 310 ~text_element_color (void) = default; 311 get_color(void)312 Matrix get_color (void) { return rgb; } 313 314 void accept (text_processor& p); 315 316 private: 317 Matrix rgb; 318 }; 319 320 class 321 OCTINTERP_API 322 text_processor 323 { 324 public: 325 virtual void visit (text_element_string& e) = 0; 326 visit(text_element_symbol &)327 virtual void visit (text_element_symbol&) { } 328 visit(text_element_list & e)329 virtual void visit (text_element_list& e) 330 { 331 for (auto& el_p : e) 332 { 333 el_p->accept (*this); 334 } 335 } 336 visit(text_element_subscript & e)337 virtual void visit (text_element_subscript& e) 338 { e.get_element ()->accept (*this); } 339 visit(text_element_superscript & e)340 virtual void visit (text_element_superscript& e) 341 { e.get_element ()->accept (*this); } 342 visit(text_element_combined &)343 virtual void visit (text_element_combined&) { } 344 visit(text_element_fontstyle &)345 virtual void visit (text_element_fontstyle&) { } 346 visit(text_element_fontname &)347 virtual void visit (text_element_fontname&) { } 348 visit(text_element_fontsize &)349 virtual void visit (text_element_fontsize&) { } 350 visit(text_element_color &)351 virtual void visit (text_element_color&) { } 352 reset(void)353 virtual void reset (void) { } 354 355 protected: text_processor(void)356 text_processor (void) { } 357 358 virtual ~text_processor (void) = default; 359 }; 360 361 #define TEXT_ELEMENT_ACCEPT(cls) \ 362 inline void \ 363 cls::accept (text_processor& p) \ 364 { \ 365 p.visit (*this); \ 366 } 367 368 TEXT_ELEMENT_ACCEPT(text_element_string) TEXT_ELEMENT_ACCEPT(text_element_symbol)369 TEXT_ELEMENT_ACCEPT(text_element_symbol) 370 TEXT_ELEMENT_ACCEPT(text_element_list) 371 TEXT_ELEMENT_ACCEPT(text_element_subscript) 372 TEXT_ELEMENT_ACCEPT(text_element_superscript) 373 TEXT_ELEMENT_ACCEPT(text_element_combined) 374 TEXT_ELEMENT_ACCEPT(text_element_fontstyle) 375 TEXT_ELEMENT_ACCEPT(text_element_fontname) 376 TEXT_ELEMENT_ACCEPT(text_element_fontsize) 377 TEXT_ELEMENT_ACCEPT(text_element_color) 378 379 class 380 OCTINTERP_API 381 text_parser 382 { 383 public: 384 text_parser (void) { } 385 386 virtual ~text_parser (void) = default; 387 388 virtual text_element * parse (const std::string& s) = 0; 389 390 public: 391 static text_element * parse (const std::string& s, 392 const caseless_str& interpreter); 393 }; 394 395 class 396 OCTINTERP_API 397 text_parser_none : public text_parser 398 { 399 public: text_parser_none(void)400 text_parser_none (void) : text_parser () { } 401 402 ~text_parser_none (void) = default; 403 404 // FIXME: is it possible to use reference counting to manage the 405 // memory for the object returned by the text parser? That would be 406 // preferable to having to know when and where to delete the object it 407 // creates... 408 parse(const std::string & s)409 text_element * parse (const std::string& s) 410 { 411 return new text_element_string (s); 412 } 413 }; 414 415 class 416 OCTINTERP_API 417 text_parser_tex : public text_parser 418 { 419 public: text_parser_tex(void)420 text_parser_tex (void) 421 : text_parser (), scanner (nullptr), buffer_state (nullptr), result (nullptr) 422 { } 423 ~text_parser_tex(void)424 ~text_parser_tex (void) 425 { destroy_lexer (); } 426 427 text_element * parse (const std::string& s); 428 get_scanner(void)429 void * get_scanner (void) { return scanner; } 430 set_parse_result(text_element * e)431 void set_parse_result (text_element *e) { result = e; } 432 get_parse_result(void)433 text_element * get_parse_result (void) { return result; } 434 435 private: 436 bool init_lexer (const std::string& s); 437 438 void destroy_lexer (void); 439 440 private: 441 void *scanner; 442 443 void *buffer_state; 444 445 text_element *result; 446 }; 447 448 inline text_element* parse(const std::string & s,const caseless_str & interpreter)449 text_parser::parse (const std::string& s, const caseless_str& interpreter) 450 { 451 std::unique_ptr<text_parser> parser; 452 453 if (interpreter.compare ("tex")) 454 parser.reset (new text_parser_tex ()); 455 else 456 parser.reset (new text_parser_none ()); 457 458 return parser->parse (s); 459 } 460 } 461 462 #if defined (OCAVE_USE_DEPRECATED_FUNCTIONS) 463 464 OCTAVE_DEPRECATED (5, "use 'octave::text_element' instead") 465 typedef octave::text_element text_element; 466 467 OCTAVE_DEPRECATED (5, "use 'octave::text_element_string' instead") 468 typedef octave::text_element_string text_element_string; 469 470 OCTAVE_DEPRECATED (5, "use 'octave::text_element_symbol' instead") 471 typedef octave::text_element_symbol text_element_symbol; 472 473 OCTAVE_DEPRECATED (5, "use 'octave::text_element_list' instead") 474 typedef octave::text_element_list text_element_list; 475 476 OCTAVE_DEPRECATED (5, "use 'octave::text_element_subscript' instead") 477 typedef octave::text_element_subscript text_element_subscript; 478 479 OCTAVE_DEPRECATED (5, "use 'octave::text_element_superscript' instead") 480 typedef octave::text_element_superscript text_element_superscript; 481 482 OCTAVE_DEPRECATED (5, "use 'octave::text_element_combined' instead") 483 typedef octave::text_element_combined text_element_combined; 484 485 OCTAVE_DEPRECATED (5, "use 'octave::text_element_fontstyle' instead") 486 typedef octave::text_element_fontstyle text_element_fontstyle; 487 488 OCTAVE_DEPRECATED (5, "use 'octave::text_element_fontname' instead") 489 typedef octave::text_element_fontname text_element_fontname; 490 491 OCTAVE_DEPRECATED (5, "use 'octave::text_element_fontsize' instead") 492 typedef octave::text_element_fontsize text_element_fontsize; 493 494 OCTAVE_DEPRECATED (5, "use 'octave::text_element_color' instead") 495 typedef octave::text_element_color text_element_color; 496 497 OCTAVE_DEPRECATED (5, "use 'octave::text_processor' instead") 498 typedef octave::text_processor text_processor; 499 500 OCTAVE_DEPRECATED (5, "use 'octave::text_parser' instead") 501 typedef octave::text_parser text_parser; 502 503 OCTAVE_DEPRECATED (5, "use 'octave::text_parser_none' instead") 504 typedef octave::text_parser_none text_parser_none; 505 506 OCTAVE_DEPRECATED (5, "use 'octave::text_parser_tex' instead") 507 typedef octave::text_parser_tex text_parser_tex; 508 509 #endif 510 511 #endif 512