/
trilirium
/
Archived_BLC
Обзор
Документация
Войти
/
trilirium
/
Archived_BLC
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
IRL_export.cpp
2 412 строк
53 KB
Trilirium
repo created OK
22 янв 2026, 16:43
22 янв 2026, 16:43
f05d14b
Код
Авторство
О чём код?
/* + === - === - === - === - === - === - === - === | | IRL_export.cpp | | Export system objects to clipboard. | + === - === - === - === - === - === - === - === */ #include "mem_mgr.h" #include "canvas.h" #include "widgets.h" #include <unistd.h> #include "textform.h" #include <cstring> #include "IRL_defs.h" // // (Character codes) // enum { // (horizontal single line) HSDiv = 0x2500, // (horizontal double line) HDDiv = 0x2550, // (solid bullet) BLSolid = 0x2022, // (trigon bullet) BLTrigon = 0x2023, // (empty bullet) BLEmpty = 0x25E6 }; // // Wide text container // struct W_Content { unsigned L_Text; // (length) wchar_t * C_Text; // (content) W_Content () { L_Text = 0; C_Text = 0; } // (is content unused??) bool _empty () { return C_Text == 0; } // (clear content) void clear () { if (C_Text) { delete [] C_Text; C_Text = 0; L_Text = 0; } } // clear // (content decoder) void decode_content (char const *tag, char const *source, A_CharCodec *codec) { if (source) C_Text = codec->decode_input (source, strlen (source), tag, L_Text); } // decode_content // (content decoder) void decode_content_len (char const *tag, char const *source, unsigned s_length, A_CharCodec *codec) { if (source) C_Text = codec->decode_input (source, s_length, tag, L_Text); } // decode_content_len }; // W_Content // // Exporter objects // // (locate character inside) int locate_char (wchar_t * Ctx, unsigned Len, wchar_t wch) { if (Ctx) { for (unsigned i = 0; i != Len; ++ i) if (Ctx[i] == wch) return i; } return -1; // fail! } // locate_char // Report export error static void report_error (A_Console &logger, char const *message, A_Dumpable &object, RemoteLink *remote) { logger. out_cstr (message). out_label (':'). out_obj_opt (remote, ""). out_obj (object). out_nl (); } // report_error // Report result (OK / failure) static void report_status (A_Console &logger, char const *message, A_Dumpable &object, RemoteLink *remote, bool status) { logger. out_cstr (message). out_label (':'). out_obj_opt (remote, ""). out_obj (object). out_cstr (" - "). out_cstr (status ? "OK." : "failed!"). out_nl (); } // report_status // [ Abstract ] struct A_Export { // abstract: // Export bytes: ptr [len] virtual bool export_b (char const *ptr, unsigned len) = 0; // abstract: // Export wchars: w_ptr [len] virtual bool export_w (wchar_t *w_ptr, unsigned len) = 0; // abstract: // Export repeated char w_char virtual bool export_r (wchar_t w_char, unsigned count) = 0; // Export С-string bool export_str (char const *str) { return export_b (str, strlen (str)); } // Export label (char) A_Export &label (char label) { export_b (&label, 1); return *this; } // label // Export label (wide char) A_Export &label_w (wchar_t label) { export_w (&label, 1); return *this; } // label_w // Export label (string) A_Export &label (char const *_label) { export_b (_label, strlen (_label)); return *this; } // label // Export label (string) A_Export &c_label (char const *_label) { if (_label) label (_label); return *this; } // c_label // Export label (string), with brackets A_Export &b_label (char left, char const *_label, char right) { export_b (&left, 1); if (_label) label (_label); export_b (&right, 1); return *this; } // b_label // Export wide text A_Export &content (W_Content &w_c) { export_w (w_c.C_Text, w_c.L_Text); return *this; } // Export (unsigned) decimal A_Export &decimal (unsigned val) { char digit = '0'; if (val) { digit += val % 10; if (val /= 10) decimal (val); } export_b (&digit, 1); return *this; } // decimal // Export hex A_Export &hex (unsigned val, bool upper) { char digit = '0'; if (val) { digit += val & 0x0F; if (digit > '9') digit += (upper ? 'A' : 'a') - '0' - 10; if (val >>= 4) hex (val, upper); } export_b (&digit, 1); return *this; } // hex // Export remote link A_Export &remote_link (RemoteLink *remote); // Export Tab A_Export &TAB () { export_b ("\t", 1); return *this; } // TAB // Export EOL A_Export &EOL () { export_b ("\r\n", 2); return *this; } // EOL // Export divider A_Export ÷r (unsigned repeat, wchar_t f_char, unsigned f_len, wchar_t e_char, unsigned e_len); // Export separated text unsigned separated (W_Content &source, wchar_t div_char, char const *divider) { wchar_t * Ctx = source.C_Text; unsigned Len = source.L_Text; unsigned count = 0; // if (Ctx [Len - 1] != div_char) // { return 0; } int index; while ((index = locate_char (Ctx, Len, div_char)) >= 0) { if (index) { if (count) label (divider); export_w (Ctx, index); } ++ index; Len -= index; Ctx += index; ++ count; } // (while) if (Len) export_w (Ctx, Len); return count + 1; } // separated }; // A_Export // [ Console exporter ] struct C_Export : A_Export { // (constructor) C_Export (RootWindow &window) { } // // (to be done) // // Export bytes: ptr[len] bool export_b (char const *ptr, unsigned len) { return false; } // Export wchars: ptr[len] bool export_w (wchar_t *w_ptr, unsigned len) { return false; } // Export repeated char bool export_r (wchar_t w_char, unsigned count) { return false; } }; // C_Export // [ Export characters counter ] struct N_Export : A_Export { unsigned total; // (constructor) N_Export () { total = 0; } // Export bytes bool export_b (char const *ptr, unsigned len) { total += len; } // Export wchars bool export_w (wchar_t *w_ptr, unsigned len) { total += len; } // Export repeated bool export_r (wchar_t w_char, unsigned count) { total += count; } }; // N_Export // [ Output buffer ] struct O_Export : A_Export { wchar_t * _buffer, * _ptr; unsigned total; // (constructor) O_Export (unsigned _total) { if (total = _total) { _buffer = new ("<O_Export>") wchar_t [_total + 1]; _buffer [_total] = L'\0'; _ptr = _buffer; } else _buffer = _ptr = 0; } // O_Export // Export bytes bool export_b (char const *ptr, unsigned len) { while (len --) *_ptr ++ = *ptr ++; return true; } // export_b // Export wchars bool export_w (wchar_t *w_ptr, unsigned len) { memcpy (_ptr, w_ptr, sizeof (wchar_t) * len); _ptr += len; return true; } // export_w // Export repeated char bool export_r (wchar_t w_char, unsigned count) { while (count --) *_ptr ++ = w_char; } // export_r // export to clipboard bool CB_export (RootWindow &window) { * _ptr = L'\0'; // (terminate) return IRL_inter::clipboard_export (window, _ptr + 1 - _buffer, _buffer); } // CB_export // (destructor) ~O_Export () { delete [] _buffer; } }; // O_Export // [ Byte stream output buffer ] struct BS_Export : A_Export { char * _buffer, * _ptr; unsigned total; // (constructor) BS_Export (unsigned _total) { if (total = _total) { _buffer = new ("<BS_Export>") char [_total + 1]; _buffer [_total] = L'\0'; _ptr = _buffer; } else _buffer = _ptr = 0; } // BS_Export // Export bytes bool export_b (char const *ptr, unsigned len) { while (len --) *_ptr ++ = *ptr ++; return true; } // export_b // Export wchars bool export_w (wchar_t *w_ptr, unsigned len) { return false; // (fail!) } // export_w // Export repeated char bool export_r (wchar_t w_char, unsigned count) { return false; } // export_r // export to clipboard bool RTF_export (RootWindow &window); // (destructor) ~BS_Export () { delete [] _buffer; } }; // BS_Export // // Free unneded codec // static void free_codec (A_CharCodec * &r_codec) { delete r_codec; r_codec = 0; } // free_codec // // Export remote link // A_Export &A_Export::remote_link (RemoteLink *remote) { if (remote) { label ('<'); c_label (remote->user_name); label ('@'); c_label (remote->host_name); label ('>'); } // (remote) } // A_Export::remote_link // // Divider: // // ((f_char * f_len) + (e_char * e_len)) * repeat // A_Export &A_Export::divider (unsigned repeat, wchar_t f_char, unsigned f_len, wchar_t e_char, unsigned e_len) { for (int i = 0; i != repeat; ++ i) { if (i) export_r (e_char, e_len); export_r (f_char, f_len); } // for (i) EOL (); } // A_Export::divider // // Export action command // struct A_Export_Op { // abstract: // start export operation virtual bool export_prepare (A_Console &logger) = 0; // abstract: // perform export (to '_export') virtual bool export_action (A_Export &_export) = 0; // abstract: // finish export virtual bool export_complete (A_Console &logger) = 0; // UTC time? static bool time_UTC; // // export entry point // bool commit_export (A_Console &_logger, bool console_out, RootWindow &window) { if (! export_prepare (_logger)) return false; // (fail!) if (console_out) { // (export to console) C_Export console_exp (window); if (! export_action (console_exp)) return false; // (fail!) } else { // (export to clipboard) N_Export _counter; // count bytes: if (export_action (_counter)) { O_Export _output (_counter.total); if (export_action (_output)) { if (! _output.CB_export (window)) { return false; // (fail!) } } else return false; // (fail!) } else return false; // (fail!) } // (success?) return export_complete (_logger); } // commit_export }; // A_Export_Op // Use UTC time?? bool A_Export_Op::time_UTC = false; // // IRL export action // struct Export_Action : IRL_command { // command constructor Export_Action (char const *cmd_name) : IRL_command (cmd_name) {} // (actual args parser, to create Export_Op) virtual A_Export_Op * export_args_parse (char const *argument) = 0; // Parse remote argument RemoteLink * parse_remote (char const *&argument) { return IRL_inter::remote_prefix (argument); } // Parse arguments: entry point bool parse_args (A_Console &logger, char const *argument) { A_Export_Op *exporter_agent = export_args_parse (argument); if (exporter_agent) { bool result = false; RootWindow *export_window = IRL_inter::create_export_window (logger); if (export_window) result = exporter_agent->commit_export (logger, false, *export_window); delete exporter_agent; return result; } // (exporter_agent) return false; } // parse_args }; // Export_Action // // Export server record // void ServerRecord::export_action (A_Export &_export) { if (user_name || host_name) { // (valid server record) _export. label ("Server: "). c_label (user_name). label ('@'). c_label (host_name). TAB (); _export. b_label ('[', client_IP.format (), ']'). b_label ('<', server_Time.format (), '>'). EOL (); } } // ServerRecord::export_action // // Export Catalog // struct Catalog_Export_Op : A_Export_Op { // (Catalog ID) CatalogID catalog; // (character codeс) A_CharCodec *codec; // (entries) unsigned entry_limit; // (remote link) RemoteLink *remote; // [ Predefines ] struct C_Predefs { char * Name; W_Content Title; W_Content About; Time When; ServerRecord S_Header; // (constructor) C_Predefs () : Title (), About (), When (0, time_UTC) { Name = 0; } // (destructor) ~C_Predefs () { Title.clear (); About.clear (); if (Name) delete Name; S_Header.release (); } // ~C_Predefs bool export_action (A_Export &_export); } * _predefs; // [ Records ] struct C_Record { bool valid; // (validity flag) HashMID Radix; W_Content Title; Time When; ServerRecord S_Record; // (constructor) C_Record () : Title (), When (0, time_UTC) // ~~ valid by default! { valid = false; } // (destructor) ~C_Record () { if (valid) { Title.clear (); S_Record.release (); } } bool export_action (A_Export &_export, unsigned no); } * _records; // constructor Catalog_Export_Op (CatalogID &_catalog, A_CharCodec *codec, RemoteLink *remote) : catalog (_catalog) { this->codec = codec; this->remote = remote; entry_limit = 0; _predefs = 0; } // Catalog_Export_Op // (when # entries is detected :) void set_limit (unsigned expected) { entry_limit = expected; } // (on startup) void on_begin () {} // (on catalog header) void on_header (char *H_Name, char *H_Title, char *H_About, Time &H_When, ServerRecord &serv_rec) { C_Predefs &predefs = *(_predefs = new ("Predefs {}") C_Predefs); predefs.Name = H_Name; predefs.S_Header.preserve (serv_rec); predefs.Title.decode_content ("{Head.Title}", H_Title, codec); delete H_Title; predefs.About.decode_content ("{Head.About}", H_About, codec); delete H_About; predefs.When = H_When; if (entry_limit) _records = new ("Records []") C_Record [entry_limit]; } // on_header // (on catalog record) void on_record (unsigned index, char *R_Title, HashMID &R_Radix, Time &R_When, ServerRecord &serv_rec) { C_Record &record = _records [index]; record.valid = true; record.S_Record.preserve (serv_rec); record.Radix = R_Radix; record.When = R_When; record.Title.decode_content ("{Rec.Title}", R_Title, codec); delete R_Title; } // on_record // (on finale) void on_finale (unsigned count) { } // // implementation // // start export operation bool export_prepare (A_Console &logger); // perform export (to '_export') bool export_action (A_Export &_export); // finish export bool export_complete (A_Console &logger); }; // Catalog_Export_Op // // Catalog export iterator // struct Iterator_CatalogExport : Server_Container_Iterator { Catalog_Export_Op &catalog_exporter; Iterator_CatalogExport (A_InOut &_inout, Catalog_Export_Op &_exporter) : Server_Container_Iterator (_inout), catalog_exporter (_exporter) {} // (on begin) bool on_begin (unsigned offset_final) { catalog_exporter.on_begin (); return true; } // on_begin // (on entry) bool on_entry (char const *entry_name, unsigned entry_index, unsigned entry_size) { Container items; ServerRecord *server_info; if (server_info = client_entry (entry_name, entry_index, entry_size)) { switch (Catalog_MetaList->lookup (entry_name, false)) { case Meta_Predefs: { items.add_empty ("EOH"); items.add_empty ("LogMode"); C_Value &C_Name = items.add_empty ("Name"); C_Value &C_Title = items.add_empty ("Title"); C_Value &C_Description = items.add_empty ("About"); C_Value &C_Time = items.add_empty ("Time"); items.update_all (_inout); Time When (0, A_Export_Op::time_UTC); When.get_content (C_Time); catalog_exporter.on_header ( CSaveVal ("header/name", C_Name), CSaveVal ("header/title", C_Title), CSaveVal ("header/about", C_Description), When, *server_info); items.release_all (CRel_Self | CRel_Body); return true; } // case Meta_Predefs case Meta_Entry: { items.add_empty ("EOM"); C_Value &C_Title = items.add_empty ("Title"); C_Value &C_Time = items.add_empty ("Time"); C_Value &C_Radix = items.add_empty ("Radix"); items.update_all (_inout); Time When (0, A_Export_Op::time_UTC); HashMID Radix; When.get_content (C_Time); Radix.get_content (C_Radix); catalog_exporter.on_record (entry_index, CSaveVal ("entry/title", C_Title), Radix, When, *server_info); items.release_all (CRel_Self | CRel_Body); return true; } // case Meta_Entry } // switch } // (server) return true; } // on_entry // (on final) bool on_final (unsigned total_count) { catalog_exporter.on_finale (total_count); return true; } // on_final }; // Iterator_CatalogExport // start export operation bool Catalog_Export_Op::export_prepare (A_Console &logger) { if (catalog.notempty ()) { PathDir store_path = IRL_inter::storage_path (remote); File_InOut inout (catalog.file_name (), store_path); if (inout.open_read ()) { unsigned entry_count = 0; Container::total_Multi (inout, entry_count); set_limit (entry_count); Iterator_CatalogExport iterator (inout, *this); bool result = Container::iterate_Multi (iterator); inout.close (); report_status (logger, "Export catalog", catalog, remote, result); return result; } else report_error (logger, "Unreadable catalog", catalog, remote); } // not empty return false; } // Catalog_Export_Op::export_prepare bool Catalog_Export_Op::C_Predefs::export_action (A_Export &_export) { if (Name) { _export.label ("Catalog: "). label (Name). EOL (); S_Header.export_action (_export); _export.label ("Created: "). label (When.format ()). EOL (); if (! Title._empty ()) _export.label ("Title: "). content (Title). EOL (); if (! About._empty ()) _export. content (About). EOL (); return true; } return false; } // Catalog_Export_Op::C_Predefs::export_action bool Catalog_Export_Op::C_Record::export_action (A_Export &_export, unsigned no) { if (valid) { S_Record.export_action (_export); _export. decimal (no + 1). label (':'). TAB (); _export. b_label ('[', Radix.refer_ID (), ']'). TAB (). b_label ('<', When.format (), '>'). EOL (); _export. TAB (). content (Title). EOL (); _export. EOL (); return true; } return false; } // Catalog_Export_Op::C_Record::export_action // perform export (to '_export') bool Catalog_Export_Op::export_action (A_Export &_export) { _export.remote_link (remote); if (_predefs) if (_predefs->export_action (_export)) _export.divider (8, HDDiv, 6, ' ', 2); if (_records) { unsigned record_count = 0; for (unsigned i = 0; i != entry_limit; ++ i) { if (_records [i].export_action (_export, record_count)) { _export.divider (8, HSDiv, 6, ' ', 2); record_count ++; } } // for (i) _export. label ("Entries: "). decimal (record_count). label ('/'). decimal (entry_limit). EOL (); } // (_records) return true; } // Catalog_Export_Op::export_action // finish export bool Catalog_Export_Op::export_complete (A_Console &logger) { logger. out_cstr ("Catalog exported."). out_nl (); if (_predefs) delete _predefs; if (_records) delete [] _records; free_codec (codec); return true; } // Catalog_Export_Op::export_complete // // Catalog export // static struct Catalog_Export_Action : Export_Action { // command constructor Catalog_Export_Action (char const *cmd_name) : Export_Action (cmd_name) {} // (actual arguments parser) A_Export_Op * export_args_parse (char const *argument) { CatalogID catalog; RemoteLink *remote = parse_remote (argument); catalog.parse (argument); return new ("IRL/Export/Catalog") Catalog_Export_Op (catalog, IRL_inter::default_Codec (1, "Codec::CatalogExport"), remote); } // export_args_parse // Report information // flag ? argument list : describe command char const * _info_about (bool flag) { return flag ? "<Catalog>" : "Export catalog"; } // _info_about } c_ExpCatalog ("CatExport"); // Catalog_Export_Action // // Callback: // Export entire catalog (Remote, ID) to clipboard // bool IRL_inter::export_Catalog (RootWindow &window, RemoteLink *Remote, CatalogID &_CatID) { Catalog_Export_Op local__Catalog (_CatID, IRL_inter::default_Codec (1, "Codec::CatalogExport"), Remote); local__Catalog.commit_export (win_console (window), false, window); } // IRL_inter::export_Catalog // // Export Message // struct Message_Export_Op : A_Export_Op { // (Radix) HashMID radix; // (character codeс) A_CharCodec *codec; // (remote link) RemoteLink *remote; // [ Message content ] struct C_Message { W_Content Title; W_Content Body; W_Content Tags; Time When; ServerRecord S_Message; // (constructor) C_Message () : Title (), Body (), Tags (), When (0, time_UTC) { } // (destructor) ~C_Message () { Title.clear (); Body.clear (); Tags.clear (); S_Message.release (); } bool export_action (A_Export &_export); } * _message; // [ Reply content ] struct C_Reply { unsigned index; W_Content Title; W_Content Body; Time When; ReplyID Parent; ServerRecord S_Reply; C_Reply * next; // next in chain // (constructor) C_Reply (char *R_Title, char *R_Body, Time &R_When, ReplyID &R_Parent, A_CharCodec *codec) : When (R_When), Parent (R_Parent) { Title.decode_content ("{Reply.Title}", R_Title, codec); delete R_Title; Body.decode_content ("{Reply.Body}", R_Body, codec); delete R_Body; next = 0; // (... nothing follows) } // C_Reply // (destructor) ~C_Reply () { Title.clear (); Body.clear (); S_Reply.release (); } bool export_action (A_Export &_export, unsigned reply_index); } * _reply; // (replies chain) // [ Append content ] struct C_Append { unsigned index; W_Content Body; Time When; ServerRecord S_Append; C_Append * next; // next in chain // (constructor) C_Append (char *R_Body, Time &R_When, A_CharCodec *codec) : When (R_When) { Body.decode_content ("{Append.Body}", R_Body, codec); delete R_Body; next = 0; // (... nothing follows) } // C_Append // (destructor) ~C_Append () { Body.clear (); S_Append.release (); } bool export_action (A_Export &_export, unsigned append_index); } * _append; // (appends chain) // constructor Message_Export_Op (HashMID &_radix, A_CharCodec *codec, RemoteLink *remote) : radix (_radix) { this->codec = codec; this->remote = remote; _message = 0; _reply = 0; _append = 0; } // Message_Export_Op // (on startup) void on_begin () { } // (on message header) void on_message (char *H_Title, char *H_Body, unsigned L_Tags, char *H_Tags, Time &H_When, ServerRecord &serv_rec) { C_Message &message = *(_message = new ("Message {}") C_Message ()); message.Title.decode_content ("{Message.Title}", H_Title, codec); delete H_Title; message.Body.decode_content ("{Message.About}", H_Body, codec); delete H_Body; message.Tags.decode_content_len ("{Message.Tags}", H_Tags, L_Tags, codec); delete H_Tags; message.When = H_When; message.S_Message.preserve (serv_rec); } // on_message // (on message reply) void on_reply (unsigned index, char *R_Title, char *R_Body, Time &R_When, ReplyID &R_Parent, ServerRecord &serv_rec) { C_Reply *reply = new ("Reply {}") C_Reply (R_Title, R_Body, R_When, R_Parent, codec); reply->S_Reply.preserve (serv_rec); reply->index = index; reply->next = _reply; _reply = reply; } // on_reply // (on message append) void on_append (unsigned index, char *R_Body, Time &R_When, ServerRecord &serv_rec) { C_Append *append = new ("Append {}") C_Append (R_Body, R_When, codec); append->S_Append.preserve (serv_rec); append->index = index; append->next = _append; _append = append; } // on_append // (on finale) void on_finale (unsigned count) { // revert replies list: C_Reply *Reply = 0; while (C_Reply *Entry = _reply) { _reply = Entry->next; Entry->next = Reply; Reply = Entry; } // (reply entry) _reply = Reply; // revert appends list: C_Append *Append = 0; while (C_Append *Entry = _append) { _append = Entry->next; Entry->next = Append; Append = Entry; } // (append entry) _append = Append; } // on_finale // // implementation // // start export operation bool export_prepare (A_Console &logger); // perform export (to '_export') bool export_action (A_Export &_export); // finish export bool export_complete (A_Console &logger); }; // Message_Export_Op // // Message export iterator // struct Iterator_MessageExport : Server_Container_Iterator { Message_Export_Op &message_exporter; Iterator_MessageExport (A_InOut &_inout, Message_Export_Op &_exporter) : Server_Container_Iterator (_inout), message_exporter (_exporter) {} // (on begin) bool on_begin (unsigned offset_final) { message_exporter.on_begin (); return true; } // on_begin // (on entry) bool on_entry (char const *entry_name, unsigned entry_index, unsigned entry_size) { Container items; ServerRecord *server_info; if (server_info = client_entry (entry_name, entry_index, entry_size)) { switch (Message_MetaList->lookup (entry_name, false)) { case Meta_Message: { items.add_empty ("EOM"); C_Value &C_Tags = items.add_empty ("Tags"); C_Value &C_Content = items.add_empty ("Body"); C_Value &C_Title = items.add_empty ("Title"); C_Value &C_Time = items.add_empty ("Time"); C_Value &C_Radix = items.add_empty ("Radix"); items.update_all (_inout); Time When (0, A_Export_Op::time_UTC); When.get_content (C_Time); message_exporter.on_message ( CSaveVal ("message/title", C_Title), CSaveVal ("message/content", C_Content), CLengthVal (C_Tags), CSaveVal ("message/tags", C_Tags), When, *server_info); items.release_all (CRel_Self | CRel_Body); return true; } // case Meta_Message case Meta_Reply: { items.add_empty ("EOR"); C_Value &C_Title = items.add_empty ("Title"); C_Value &C_Body = items.add_empty ("Body"); C_Value &C_Time = items.add_empty ("Time"); C_Value &C_Parent = items.add_empty ("Parent"); items.update_all (_inout); Time When (0, A_Export_Op::time_UTC); When.get_content (C_Time); ReplyID Parent; Parent.clear (); if (CLengthVal (C_Parent)) Parent.get_content (C_Parent); message_exporter.on_reply (entry_index, CSaveVal ("reply/title", C_Title), CSaveVal ("reply/body", C_Body), When, Parent, *server_info); items.release_all (CRel_Self | CRel_Body); return true; } // case Meta_Reply case Meta_Append: { items.add_empty ("EOR"); C_Value &C_Body = items.add_empty ("Body"); C_Value &C_Time = items.add_empty ("Time"); items.update_all (_inout); Time When (0, A_Export_Op::time_UTC); When.get_content (C_Time); message_exporter.on_append (entry_index, CSaveVal ("reply/body", C_Body), When, *server_info); items.release_all (CRel_Self | CRel_Body); return true; } // case Meta_Append } // switch } // (not server) return true; } // on_entry // (on final) bool on_final (unsigned total_count) { message_exporter.on_finale (total_count); return true; } // on_final }; // Iterator_MessageExport // start export operation bool Message_Export_Op::export_prepare (A_Console &logger) { PathDir store_path = IRL_inter::storage_path (remote); File_InOut inout (radix.file_name (), store_path); if (inout.open_read ()) { unsigned entry_count = 0; Container::total_Multi (inout, entry_count); Iterator_MessageExport iterator (inout, *this); bool result = Container::iterate_Multi (iterator); inout.close (); report_status (logger, "Export message", radix, remote, result); return result; } else report_error (logger, "Unreadable message", radix, remote); return false; } // Message_Export_Op::export_prepare bool Message_Export_Op::C_Message::export_action (A_Export &_export) { S_Message.export_action (_export); if (! Title._empty ()) _export.label ("Posted: "). label (When.format ()). EOL (); _export.label ("Title: "). content (Title). EOL (); if (! Body._empty ()) _export.label ("Body: "). EOL (). content (Body). EOL (); if (! Tags._empty ()) { _export.label ("Tags: "); _export.separated (Tags, 0, " / "); _export. EOL (); } return true; } // Message_Export_Op::C_Message::export_action bool Message_Export_Op::C_Reply::export_action (A_Export &_export, unsigned reply_index) { _export. decimal (reply_index + 1). label ('/'). decimal (index). label (':'). TAB (); S_Reply.export_action (_export); _export.label ("Replied: "). label (When.format ()). EOL (); if (! Parent.empty ()) _export.label ("Parent: "). label (Parent.refer_ID ()). EOL (); if (! Title._empty ()) _export.label ("Title: "). content (Title). EOL (); if (! Body._empty ()) _export.label ("Reply: "). EOL (). content (Body). EOL (); return true; } // Message_Export_Op::C_Reply::export_action bool Message_Export_Op::C_Append::export_action (A_Export &_export, unsigned append_index) { _export. decimal (append_index + 1). label ('/'). decimal (index). label (':'). TAB (); S_Append.export_action (_export); _export.label ("Appended: "). label (When.format ()). EOL (); if (! Body._empty ()) _export.label ("Append: "). EOL (). content (Body). EOL (); return true; } // Message_Export_Op::C_Append::export_action // perform export (to '_export') bool Message_Export_Op::export_action (A_Export &_export) { _export.label ("Message: "); _export.remote_link (remote); _export.b_label ('[', radix.refer_ID (), ']'). EOL (). EOL (); if (_message) if (_message->export_action (_export)) _export.divider (8, HDDiv, 6, ' ', 2); unsigned append_count = 0; for (C_Append * append = _append; append; append = append->next) if (append->export_action (_export, append_count)) { _export.divider (6, HSDiv, 8, ' ', 2); ++ append_count; } if (append_count) _export.label ("Appends: total "). decimal (append_count). EOL (); else _export.label ("Appends: none."). EOL (); unsigned reply_count = 0; for (C_Reply * reply = _reply; reply; reply = reply->next) if (reply->export_action (_export, reply_count)) { _export.divider (6, HSDiv, 8, ' ', 2); ++ reply_count; } if (reply_count) _export.label ("Replies: total "). decimal (reply_count). EOL (); else _export.label ("Replies: none."). EOL (); return true; } // Message_Export_Op::export_action // finish export bool Message_Export_Op::export_complete (A_Console &logger) { logger. out_cstr ("Message exported."). out_nl (); if (_message) { delete _message; _message = 0; } while (C_Reply *reply = _reply) { _reply = reply->next; delete reply; } // while (reply) while (C_Append *append = _append) { _append = append->next; delete append; } // while (append) free_codec (codec); return true; } // Message_Export_Op::export_complete // // Message export // static struct Message_Export_Action : Export_Action { // command constructor Message_Export_Action (char const *cmd_name) : Export_Action (cmd_name) {} // (actual arguments parser) A_Export_Op * export_args_parse (char const *argument) { HashMID radix; RemoteLink *remote = parse_remote (argument); radix.parse (argument); return new ("IRL/Export/Message") Message_Export_Op (radix, IRL_inter::default_Codec (1, "Codec::MessageExport"), remote); } // export_args_parse // Report information // flag ? argument list : describe command char const * _info_about (bool flag) { return flag ? "<Radix>" : "Export message"; } // _info_about } c_ExpMessage ("MsgExport"); // Message_Export_Action // // Callback: // Export message content to clipboard // bool IRL_inter::export_Message (RootWindow &window, RemoteLink *Remote, HashMID &Radix) { Message_Export_Op local__Message (Radix, IRL_inter::default_Codec (1, "Codec::MessageExport"), Remote); local__Message.commit_export (win_console (window), false, window); } // IRL_inter::export_Message // // Export TagList // struct TagList_Export_Op : A_Export_Op { // (Hash tag) HashTag H_Tag; // (character codeс) A_CharCodec *codec; // (remote link) RemoteLink *remote; W_Content H_Title; // (tag title) Time H_When; // (create time) // (head server record) ServerRecord S_TagHead; // [ Reference entry ] struct C_Refer { unsigned index; W_Content Title; Time When; HashMID Radix; ServerRecord S_Refer; // (constructor) C_Refer () : Title (), When (0, A_Export_Op::time_UTC) { index = ~0; } // (destructor) ~C_Refer () { Title.clear (); S_Refer.release (); } bool export_action (A_Export &_export, unsigned no); } * _references; unsigned refer_count; // constructor TagList_Export_Op (HashTag &_hashtag, A_CharCodec *codec, RemoteLink *remote) : H_Tag (false, _hashtag), H_When (0, time_UTC) { if (H_Tag.tagcode) { H_Tag.calc_hash (); H_Tag.content_encoder (); } this->codec = codec; this->remote = remote; _references = 0; } // TagList_Export_Op // (set container capacity) void set_capacity (unsigned entry_count) { refer_count = entry_count; _references = new ("TagRefs []") C_Refer [entry_count]; } // set_capacity // (on startup) void on_begin () { } // (on tags header) void on_initial (HashTag &H_Tag, Time &_When, ServerRecord &serv_rec) { H_Title.decode_content ("{Taglist.Title}", H_Tag.text_of (), codec); H_When = _When; S_TagHead.preserve (serv_rec); } // on_initial // (on tags reference) void on_reference (unsigned index, char *R_Title, HashMID &Radix, Time &R_When, ServerRecord &serv_rec) { if (_references) { C_Refer &_entry = _references [index]; _entry.index = index; _entry.Title.decode_content ("{Tagref.Title}", R_Title, codec); _entry.Radix = Radix; _entry.When = R_When; _entry.S_Refer.preserve (serv_rec); delete R_Title; } } // on_reference // (on finale) void on_finale (unsigned count) { } // on_finale // // implementation // // start export operation bool export_prepare (A_Console &logger); // perform export (to '_export') bool export_action (A_Export &_export); // finish export bool export_complete (A_Console &logger); }; // TagList_Export_Op // // Tag list export iterator // struct Iterator_TagListExport : Server_Container_Iterator { TagList_Export_Op &tags_exporter; Iterator_TagListExport (A_InOut &_inout, TagList_Export_Op &_exporter) : Server_Container_Iterator (_inout), tags_exporter (_exporter) {} // Entry tag types enum TagListExp_Tag { Meta_Null, Meta_Init, Meta_Refer }; // (on begin) bool on_begin (unsigned offset_final) { tags_exporter.on_begin (); return true; } // on_begin // (on entry) bool on_entry (char const *entry_name, unsigned entry_index, unsigned entry_size) { Container items; ServerRecord *server_info; if (server_info = client_entry (entry_name, entry_index, entry_size)) { switch (TagList_MetaList->lookup (entry_name, false)) { case Meta_Init: { // (initial record) C_Value &C_Time = items.add_empty ("CreaTime"); C_Value &C_HashA = items.add_empty ("HashVal"); C_Value &C_Hash = items.add_empty ("Hash_V"); items.update_all (_inout); HashTag H_Tag; H_Tag.get_content (CTestVal (C_HashA) ? C_HashA : C_Hash); Time When (0, A_Export_Op::time_UTC); When.get_content (C_Time); tags_exporter.on_initial (H_Tag, When, *server_info); items.release_all (CRel_Self | CRel_Body); return true; } // Meta_Init case Meta_Refer: { // (reference entry) C_Value &C_Title = items.add_empty ("Title"); C_Value &C_Time = items.add_empty ("Time"); C_Value &C_Radix = items.add_empty ("Radix"); items.update_all (_inout); Time When (0, A_Export_Op::time_UTC); When.get_content (C_Time); HashMID Radix; Radix.get_content (C_Radix); tags_exporter.on_reference (entry_index, CSaveVal ("refer/title", C_Title), Radix, When, *server_info); items.release_all (CRel_Self | CRel_Body); return true; } // case Meta_Refer } // switch } return true; } // on_entry // (on final) bool on_final (unsigned total_count) { tags_exporter.on_finale (total_count); return true; } // on_final }; // Iterator_TagListExport // start export operation bool TagList_Export_Op::export_prepare (A_Console &logger) { PathDir store_path = IRL_inter::storage_path (remote); File_InOut inout (H_Tag.file_name (), store_path); if (inout.open_read ()) { unsigned entry_count = 0; Container::total_Multi (inout, entry_count); set_capacity (entry_count); Iterator_TagListExport iterator (inout, *this); bool result = Container::iterate_Multi (iterator); inout.close (); report_status (logger, "Export tag list", H_Tag, remote, result); return result; } else report_error (logger, "Unreadable tag list", H_Tag, remote); return false; } // TagList_Export_Op::export_prepare bool TagList_Export_Op::C_Refer::export_action (A_Export &_export, unsigned no) { if (~index) { _export. label_w (BLEmpty). decimal (no). EOL (); S_Refer.export_action (_export); if (! Title._empty ()) _export.label ("Title: "). content (Title). EOL (); _export. b_label ('[', Radix.refer_ID (), ']'). TAB (). b_label ('<', When.format (), '>'). EOL (); _export. EOL (); return true; } return false; } // TagList_Export_Op::C_Refer::export_action // perform export (to '_export') bool TagList_Export_Op::export_action (A_Export &_export) { _export.remote_link (remote); _export.label ('#'). label (H_Tag.refer_ID ()). EOL (); S_TagHead.export_action (_export); if (! H_Title._empty ()) _export.label ("Tag: "). content (H_Title). EOL (); _export.label ("Created: "). label (H_When.format ()). EOL (); if (_references) { _export.divider (6, HSDiv, 8, ' ', 2); for (unsigned i = 0; i != refer_count; ++ i) _references [i].export_action (_export, i); } _export.divider (4, HSDiv, 4, ' ', 2); _export.label ("Total entries: "). decimal (refer_count). EOL (); return true; } // TagList_Export_Op::export_action // finish export bool TagList_Export_Op::export_complete (A_Console &logger) { logger. out_cstr ("Tag list exported."). out_nl (); if (_references) { delete [] _references; } H_Title.clear (); S_TagHead.release (); free_codec (codec); return true; } // TagList_Export_Op::export_complete static struct TagList_Export_Action : Export_Action { // command constructor TagList_Export_Action (char const *cmd_name) : Export_Action (cmd_name) {} // (actual arguments parser) A_Export_Op * export_args_parse (char const *argument) { HashTag H_Tag; RemoteLink *remote = parse_remote (argument); H_Tag.parse (argument); return new ("IRL/Export/TagList") TagList_Export_Op (H_Tag, IRL_inter::default_Codec (1, "Codec::TagListExport"), remote); } // export_args_parse // Report information // flag ? argument list : describe command char const * _info_about (bool flag) { return flag ? "<HashTag>" : "Export tags list"; } // _info_about } c_ExpTags ("TagsExport"); // TagList_Export_Action // // Callback: // Export tag list content to clipboard // bool IRL_inter::export_Tags (RootWindow &window, RemoteLink *Remote, HashTag &H_Tag) { HashTag local_tag (false, H_Tag); TagList_Export_Op local__Tags (local_tag, IRL_inter::default_Codec (1, "Codec::TagListExport"), Remote); local__Tags.commit_export (win_console (window), false, window); } // IRL_inter::export_Tags // // Export user profile // struct Profile_Export_Op : A_Export_Op { // (character codeс) A_CharCodec *codec; // (remote link) RemoteLink *remote; ServerRecord S_Profile; Time When; // (create time) // (profile info) W_Content Info_Brief, Info_Full, Info_Tags; // constructor Profile_Export_Op (A_CharCodec *codec, RemoteLink *remote) : When (0, time_UTC) { this->codec = codec; this->remote = remote; } // Profile_Export_Op // // implementation // // start export operation bool export_prepare (A_Console &logger); // perform export (to '_export') bool export_action (A_Export &_export); // finish export bool export_complete (A_Console &logger); }; // Profile_Export_Op bool Profile_Export_Op::export_prepare (A_Console &logger) { char const *file_name = "_profile.blc"; Container items; items.add_empty ("EOD"); C_Value &C_Time = items.add_empty ("CreaTime"); C_Value &C_Tags = items.add_empty ("UserTags"); C_Value &C_Full = items.add_empty ("InfoFull"); C_Value &C_Brief = items.add_empty ("InfoBrief"); bool outcome; if (outcome = IRL_inter::Remote_retrieve (logger, remote, file_name, Profile_MetaList->lookup (Meta_Info, false), 0, &S_Profile, items)) { When.get_content (C_Time); char *R_Brief = CSaveVal ("profile/brief", C_Brief); Info_Brief.decode_content ("{Profile.Brief}", R_Brief, codec); delete R_Brief; char *R_Full = CSaveVal ("profile/full", C_Full); Info_Full.decode_content ("{Profile.Full}", R_Full, codec); delete R_Full; char *R_Tags = CSaveVal ("profile/tags", C_Tags); Info_Tags.decode_content ("{Profile.Tags}", R_Tags, codec); delete R_Tags; } // (outcome) else { StringObj _profile ("<profile>"); report_error (logger, "Unreadable profile", _profile, remote); } items.release_all (CRel_Self | CRel_Body); return outcome; } // Profile_Export_Op::export_prepare // perform export (to '_export') bool Profile_Export_Op::export_action (A_Export &_export) { _export.remote_link (remote); S_Profile.export_action (_export); _export.divider (6, HSDiv, 3, ' ', 2); if (! Info_Brief._empty ()) _export.label ("Brief: "). content (Info_Brief). EOL (); if (! Info_Full._empty ()) _export.label ("Full: "). content (Info_Full). EOL (); if (! Info_Tags._empty ()) _export.label ("Tags: "). content (Info_Tags). EOL (); return true; } // Profile_Export_Op::export_action // finish export bool Profile_Export_Op::export_complete (A_Console &logger) { logger. out_cstr ("Profile exported."). out_nl (); S_Profile.release (); Info_Brief.clear (); Info_Full.clear (); Info_Tags.clear (); free_codec (codec); return true; } // Profile_Export_Op::export_complete // // Callback: // Export user profile content to clipboard // bool IRL_inter::export_Profile (RootWindow &window, RemoteLink *Remote) { Profile_Export_Op local__Profile (IRL_inter::default_Codec (1, "Codec::ProfileExport"), Remote); local__Profile.commit_export (win_console (window), false, window); } // IRL_inter::export_Profile static struct Profile_Export_Action : Export_Action { // command constructor Profile_Export_Action (char const *cmd_name) : Export_Action (cmd_name) {} // (actual arguments parser) A_Export_Op * export_args_parse (char const *argument) { RemoteLink *remote = parse_remote (argument); return new ("IRL/Export/Profile") Profile_Export_Op (IRL_inter::default_Codec (1, "Codec::ProfileExport"), remote); } // export_args_parse // Report information // flag ? argument list : describe command char const * _info_about (bool flag) { return flag ? "<>" : "Export user profile"; } // _info_about } c_ExpProfile ("ProfileExport"); // Profile_Export_Action // // Export IRL/URL // struct URL_Export_Op : A_Export_Op { char const *prefix; char const *URL; URL_Export_Op (char const *prefix, char const *URL) { this->prefix = prefix; this->URL = URL; } // start export operation bool export_prepare (A_Console &logger); // perform export (to '_export') bool export_action (A_Export &_export); // finish export bool export_complete (A_Console &logger); }; // URL_Export_Op // start export operation bool URL_Export_Op::export_prepare (A_Console &logger) { return true; } // perform export (to '_export') bool URL_Export_Op::export_action (A_Export &_export) { _export.label (prefix). label (':'). label (URL). EOL (); } // finish export operation bool URL_Export_Op::export_complete (A_Console &logger) { return true; } static struct URL_Export_Action : Export_Action { char const *prefix; // command constructor URL_Export_Action (char const *cmd_name, char const *_prefix) : Export_Action (cmd_name) { prefix = _prefix; } // (actual args parser) A_Export_Op * export_args_parse (char const *argument) { if (argument) return new ("IRL/Export/URL") URL_Export_Op (prefix, argument); return 0; // (nothing to export!) } // export_args_parse // Report information // flag ? argument list : describe command char const * _info_about (bool flag) { return flag ? "<URL/IRL>" : "Export URL or IRL"; } // _info_about } c_ExpURL ("URLExport", "URL"), c_ExpIRL ("IRLExport", "IRL"); // URL_Export_Action // // Control variables ::: // static IRL_Boolean C_UTC_Time ("Time_UTC_X", A_Export_Op::time_UTC); // // // Export content // // // (format flags) enum { FORM_NULL = 0, FORM_RTF = 1, FORM_BEFORE = 0 << 8, FORM_AFTER = 1 << 8 }; static bool export_tree (TFE_Term *root, A_Export &exporter, unsigned format_def) { char Blank = ' '; while (root) { TFE_Attr *child = root->as_Attr (); root->exporter (exporter, format_def); exporter.export_b (&Blank, 1); if (child) { export_tree (child->list, exporter, format_def); child->exporter (exporter, format_def ^ FORM_AFTER); } root = root->next; } // while (root) } // export_tree // (export Term) bool TFE_Term::exporter (A_Export &exporter, unsigned format_def) { return true; } // TFE_Term::exporter // (export Attr) bool TFE_Attr::exporter (A_Export &exporter, unsigned format_def) { return true; } // TFE_Attr::exporter // (export ASCII char) bool TFE_Char::exporter (A_Export &exporter, unsigned format_def) { exporter.export_b (&Code, 1); return true; } // TFE_Char::exporter // (export ASCII text) bool TFE_Text::exporter (A_Export &exporter, unsigned format_def) { exporter.export_b (Text, Len); return true; } // TFE_Text::exporter // (export unicode char FAST) static bool UC_char_export (A_Export &exporter, wchar_t Code) { enum { _BufLen = 16 }; // (enough space) char _buffer [_BufLen]; char *ptr = _buffer + _BufLen; *-- ptr = '?'; // (char terminator) do *-- ptr = '0' + (Code % 10); while (Code /= 10); // (prefix) *-- ptr = 'u'; // () *-- ptr = '\\'; // () return exporter.export_b (ptr, _buffer + _BufLen - ptr); } // UC_char_export // (export Unicode char) bool TFE_W_Char::exporter (A_Export &exporter, unsigned format_def) { return UC_char_export (exporter, W_Code); } // TFE_W_Char::exporter // (export Unicode text) bool TFE_W_Text::exporter (A_Export &exporter, unsigned format_def) { for (unsigned i = 0; i != Len; ++ i) if (! UC_char_export (exporter, W_Text [i])) return false; return true; } // TFE_W_Text::exporter // // Attributes: // // (export Bold) bool TFE_A_Bold::exporter (A_Export &exporter, unsigned format_def) { return exporter.export_str (format_def & FORM_AFTER ? "\\b0" : "\\b1"); } // (export Italic) bool TFE_A_Italic::exporter (A_Export &exporter, unsigned format_def) { return exporter.export_str (format_def & FORM_AFTER ? "\\i0" : "\\i1"); } // (export Underline) bool TFE_A_ULine::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export Overstrike) bool TFE_A_OStrike::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export Font face) bool TFE_A_FontFace::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export Font size) bool TFE_A_FontSize::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export Font width) bool TFE_A_FontWidth::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export Font color) bool TFE_A_FontColor::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export Font back color) bool TFE_A_BackColor::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export Font effect) bool TFE_A_FontEffect::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export Paragraph) bool TFE_A_Para::exporter (A_Export &exporter, unsigned format_def) { return exporter.export_str (format_def & FORM_AFTER ? "\\pard" : "\\par"); } // (export ParaLine) bool TFE_A_ParaLines::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export paragraph break) bool TFE_ParaBreak::exporter (A_Export &exporter, unsigned format_def) { return true; } // (export word glue) bool TFE_WordGlue::exporter (A_Export &exporter, unsigned format_def) { return true; } // (export word nail) bool TFE_WordNail::exporter (A_Export &exporter, unsigned format_def) { return true; } // (export Para meter) bool TFE_A_ParaMeter::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export Para align) bool TFE_A_ParaAlign::exporter (A_Export &exporter, unsigned format_def) { return TFE_Attr::exporter (exporter, format_def); } // (export style def) bool TFE_A_DefStyle::exporter (A_Export &exporter, unsigned format_def) { return true; } // (export style apply) bool TFE_A_WithStyle::exporter (A_Export &exporter, unsigned format_def) { return true; } // (export comment) bool TFE_A_Comment::exporter (A_Export &exporter, unsigned format_def) { return true; } // // Actual export: // struct Export_TFE : A_Export_Op { TFE_Term *node; unsigned format_def; // constructor Export_TFE (TFE_Term *root, unsigned format_def) { this->node = root; this->format_def = format_def; } // start export operation bool export_prepare (A_Console &logger); // perform export (to '_export') bool export_action (A_Export &_export); // finish export bool export_complete (A_Console &logger); }; // Export_TFE // Start export operation bool Export_TFE::export_prepare (A_Console &logger) { // (do nothing) return true; } // Export_TFE::export_prepare // Perform export (to '_export') bool Export_TFE::export_action (A_Export &_export) { export_tree (node, _export, format_def); return true; } // Export_TFE::export_action // Finish export bool Export_TFE::export_complete (A_Console &logger) { return true; } // Export_TFE::export_complete bool BS_Export::RTF_export (RootWindow &window) { bool RTF_to_clipboard (char *buffer, unsigned count); * _ptr = '\0'; // (terminate) return RTF_to_clipboard (_buffer, _ptr + 1 - _buffer); } // BS_Export::RTF_export static bool Format_export (A_Export_Op &exporter, A_Console &_logger, bool console_out, RootWindow &window) { if (! exporter.export_prepare (_logger)) return false; // (fail!) if (console_out) { // (export to console) C_Export console_exp (window); if (! exporter.export_action (console_exp)) return false; // (fail!) } else { // (export to clipboard) N_Export _counter; // count bytes: if (exporter.export_action (_counter)) { BS_Export _output (_counter.total); _logger.out_label ("Export count:"). out_dec (_counter.total). out_nl (); if (exporter.export_action (_output)) { if (! _output.RTF_export (window)) { return false; // (fail!) } } else return false; // (fail!) } else return false; // (fail!) } // (success?) return exporter.export_complete (_logger); } // Format_export // // Export content joiner // struct Export_Container : A_Export_Op { // (nodes list) struct Export_Node { A_Export_Op *element; Export_Node *next; // (node prolog/epilog) char const *in_prolog, *in_epilog; } * first; // (global prolog/epilog) char const *ex_prolog, *ex_epilog; // constructor Export_Container (char const *ex_prolog, char const *ex_epilog) { this->ex_prolog = ex_prolog, this->ex_epilog = ex_epilog; first = 0; } // Export_Container // append entry void append (A_Export_Op *entry, char const *in_prolog, char const *in_epilog) { Export_Node *node = new ("Export_Node") Export_Node; node->element = entry; node->next = first; first = node; node->in_prolog = in_prolog, node->in_epilog = in_epilog; } // append // reverse entries void revert () { Export_Node *list = 0; while (first) { Export_Node *next = first->next; first->next = list; list = first; first = next; } // while first = list; } // revert // start export operation bool export_prepare (A_Console &logger) { for (Export_Node *node = first; node; node = node->next) { if (! node->element->export_prepare (logger)) return false; } return true; } // export_prepare // perform export (to '_export') bool export_action (A_Export &_export) { if (! _export.export_str (ex_prolog)) return false; for (Export_Node *node = first; node; node = node->next) { if (! _export.export_str (node->in_prolog)) return false; if (! node->element->export_action (_export)) return false; if (! _export.export_str (node->in_epilog)) return false; } // for (node) if (! _export.export_str (ex_epilog)) return false; // (success!) return true; } // export_action // finish export operation bool export_complete (A_Console &logger) { for (Export_Node *node = first; node; node = node->next) if (! node->element->export_prepare (logger)) return false; return true; } // export_complete // clean up entries void cleanup () { Export_Node *node; while (node = first) { first = node->next; delete node->element; delete node; } } // cleanup }; // Export_Container // // Interface: ExportCollection // // (constructor) ExportCollection::ExportCollection () { container = new ("[ExportContainer]") Export_Container ("{\\rtf1\\ansi", "}"); } // ExportCollection::ExportCollection // add simple textbox entry to export W_TextBox * ExportCollection::add_export_entry (char const *info_tag, char const *text_title, struct W_TextBox *text_entry) { unsigned format_def = 0; // Append: title. if (container) { Export_TFE *entry = new (info_tag) Export_TFE (text_entry->content, format_def); container->append (entry, "\\pard", "\\par"); } return text_entry; } // ExportCollection::add_export_entry // do export content bool ExportCollection::complete_export (char const *format_type, RootWindow &window) { if (container) { container->revert (); return Format_export (*container, *window.logger, false, window); } return false; } // ExportCollection::complete_export // (destructor) ExportCollection::~ExportCollection () { if (container) { container->cleanup (); delete container; container = 0; } } // ExportCollection::~ExportCollection