diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/administration.cpp | 162 | ||||
| -rw-r--r-- | src/locales.cpp | 3 | ||||
| -rw-r--r-- | src/ui/helpers.cpp | 39 | ||||
| -rw-r--r-- | src/ui/ui_contacts.cpp | 92 | ||||
| -rw-r--r-- | src/ui/ui_invoices.cpp | 15 | ||||
| -rw-r--r-- | src/ui/ui_main.cpp | 34 | ||||
| -rw-r--r-- | src/ui/ui_projects.cpp | 10 | ||||
| -rw-r--r-- | src/ui/ui_settings.cpp | 35 |
8 files changed, 340 insertions, 50 deletions
diff --git a/src/administration.cpp b/src/administration.cpp index fb8bd21..5e323d0 100644 --- a/src/administration.cpp +++ b/src/administration.cpp @@ -8,17 +8,169 @@ administration g_administration; +static void administration_create_default_tax_brackets() +{ + #define ADD_BRACKET(_country, _rate, _description)\ + {\ + country_tax_bracket* tb = (country_tax_bracket*)malloc(sizeof(country_tax_bracket));\ + memcpy(tb->country_code, _country, sizeof(tb->country_code));\ + tb->rate = _rate;\ + memcpy(tb->description, _country, sizeof(tb->description));\ + list_append(&g_administration.tax_brackets, tb);\ + } + + // General brackets shared between countries. + ADD_BRACKET("00", 0.0f, "tax.reverse_charge"); + ADD_BRACKET("00", 0.0f, "tax.exempt"); + + // Austria + ADD_BRACKET("AT", 20.0f, "Standard"); + ADD_BRACKET("AT", 10.0f, "Reduced"); + ADD_BRACKET("AT", 13.0f, "Reduced"); + + // Belgium + ADD_BRACKET("BE", 21.0f, "Standard"); + ADD_BRACKET("BE", 6.0f, "Reduced"); + ADD_BRACKET("BE", 12.0f, "Reduced"); + + // Bulgaria + ADD_BRACKET("BG", 20.0f, "Standard"); + ADD_BRACKET("BG", 9.0f, "Reduced"); + + // Cyprus + ADD_BRACKET("CY", 19.0f, "Standard"); + ADD_BRACKET("CY", 5.0f, "Reduced"); + ADD_BRACKET("CY", 9.0f, "Reduced"); + + // Czechia + ADD_BRACKET("CZ", 21.0f, "Standard"); + ADD_BRACKET("CZ", 12.0f, "Reduced"); + + // Croatia + ADD_BRACKET("HR", 25.0f, "Standard"); + ADD_BRACKET("HR", 5.0f, "Reduced"); + ADD_BRACKET("HR", 13.0f, "Reduced"); + + // Denmark + ADD_BRACKET("DK", 25.0f, "Standard"); + + // Estonia + ADD_BRACKET("EE", 22.0f, "Standard"); + ADD_BRACKET("EE", 9.0f, "Reduced"); + + // Finland + ADD_BRACKET("FI", 25.5f, "Standard"); + ADD_BRACKET("FI", 10.0f, "Reduced"); + ADD_BRACKET("FI", 14.0f, "Reduced"); + + // France + ADD_BRACKET("FR", 20.0f, "Standard"); + ADD_BRACKET("FR", 5.5f, "Reduced"); + ADD_BRACKET("FR", 10.0f, "Reduced"); + ADD_BRACKET("FR", 2.1f, "SuperReduced"); + + // Germany + ADD_BRACKET("DE", 19.0f, "Standard"); + ADD_BRACKET("DE", 7.0f, "Reduced"); + + // Greece + ADD_BRACKET("GR", 24.0f, "Standard"); + ADD_BRACKET("GR", 6.0f, "Reduced"); + ADD_BRACKET("GR", 13.0f, "Reduced"); + + // Hungary + ADD_BRACKET("HU", 27.0f, "Standard"); + ADD_BRACKET("HU", 5.0f, "Reduced"); + ADD_BRACKET("HU", 18.0f, "Reduced"); + + // Ireland + ADD_BRACKET("IE", 23.0f, "Standard"); + ADD_BRACKET("IE", 9.0f, "Reduced"); + ADD_BRACKET("IE", 13.5f, "Reduced"); + ADD_BRACKET("IE", 4.8f, "SuperReduced"); + + // Italy + ADD_BRACKET("IT", 22.0f, "Standard"); + ADD_BRACKET("IT", 5.0f, "Reduced"); + ADD_BRACKET("IT", 10.0f, "Reduced"); + ADD_BRACKET("IT", 4.0f, "SuperReduced"); + + // Latvia + ADD_BRACKET("LV", 21.0f, "Standard"); + ADD_BRACKET("LV", 5.0f, "Reduced"); + ADD_BRACKET("LV", 12.0f, "Reduced"); + + // Lithuania + ADD_BRACKET("LT", 21.0f, "Standard"); + ADD_BRACKET("LT", 5.0f, "Reduced"); + ADD_BRACKET("LT", 9.0f, "Reduced"); + + // Luxembourg + ADD_BRACKET("LU", 17.0f, "Standard"); + ADD_BRACKET("LU", 8.0f, "Reduced"); + ADD_BRACKET("LU", 14.0f, "Reduced"); + ADD_BRACKET("LU", 3.0f, "SuperReduced"); + + // Malta + ADD_BRACKET("MT", 18.0f, "Standard"); + ADD_BRACKET("MT", 5.0f, "Reduced"); + ADD_BRACKET("MT", 7.0f, "Reduced"); + + // Netherlands + ADD_BRACKET("NL", 21.0f, "Standard"); + ADD_BRACKET("NL", 9.0f, "Reduced"); + + // Poland + ADD_BRACKET("PL", 23.0f, "Standard"); + ADD_BRACKET("PL", 5.0f, "Reduced"); + ADD_BRACKET("PL", 8.0f, "Reduced"); + + // Portugal + ADD_BRACKET("PT", 23.0f, "Standard"); + ADD_BRACKET("PT", 6.0f, "Reduced"); + ADD_BRACKET("PT", 13.0f, "Reduced"); + + // Romania + ADD_BRACKET("RO", 19.0f, "Standard"); + ADD_BRACKET("RO", 5.0f, "Reduced"); + ADD_BRACKET("RO", 9.0f, "Reduced"); + + // Slovakia + ADD_BRACKET("SK", 23.0f, "Standard"); + ADD_BRACKET("SK", 5.0f, "Reduced"); + ADD_BRACKET("SK", 19.0f, "Reduced"); + + // Slovenia + ADD_BRACKET("SI", 22.0f, "Standard"); + ADD_BRACKET("SI", 5.0f, "Reduced"); + ADD_BRACKET("SI", 9.5f, "Reduced"); + + // Spain + ADD_BRACKET("ES", 21.0f, "Standard"); + ADD_BRACKET("ES", 10.0f, "Reduced"); + ADD_BRACKET("ES", 4.0f, "SuperReduced"); + + // Sweden + ADD_BRACKET("SE", 25.0f, "Standard"); + ADD_BRACKET("SE", 6.0f, "Reduced"); + ADD_BRACKET("SE", 12.0f, "Reduced"); +} + void administration_create() { list_init(&g_administration.contacts); list_init(&g_administration.projects); + list_init(&g_administration.tax_brackets); strops_copy(g_administration.path, "[unsaved project]", sizeof(g_administration.path)); // @localize + + administration_create_default_tax_brackets(); } void administration_destroy() { list_destroy(&g_administration.contacts); list_destroy(&g_administration.projects); + list_destroy(&g_administration.tax_brackets); } bool administration_create_contact(contact data) @@ -195,4 +347,14 @@ bool administration_remove_project(project data) list_iterator_stop(&g_administration.projects); return false; +} + +contact administration_get_company_info() +{ + return g_administration.company_info; +} + +void administration_set_company_info(contact data) +{ + g_administration.company_info = data; }
\ No newline at end of file diff --git a/src/locales.cpp b/src/locales.cpp index 6ec1233..363d3c9 100644 --- a/src/locales.cpp +++ b/src/locales.cpp @@ -1,3 +1,6 @@ +#include <stdio.h> +#include <string.h> + #include "locales.hpp" locale_map locales[] = { diff --git a/src/ui/helpers.cpp b/src/ui/helpers.cpp index 74876c0..e4b25c8 100644 --- a/src/ui/helpers.cpp +++ b/src/ui/helpers.cpp @@ -2,7 +2,44 @@ #include "imgui.h" #include "locales.hpp" -void view_draw_required_tag() +static float toast_timer = 0.0f; +static const char* toast_msg = nullptr; +void ui_helper_show_toast(const char* msg) +{ + toast_msg = msg; + toast_timer = 3.0f; +} + +void ui_helper_draw_toasts() +{ + if (toast_timer > 0.0f && toast_msg) + { + toast_timer -= ImGui::GetIO().DeltaTime; + + const float pad = 10.0f; + const ImVec2 window_pos = ImVec2( + ImGui::GetIO().DisplaySize.x - pad, + ImGui::GetIO().DisplaySize.y - pad + ); + const ImVec2 window_pos_pivot = ImVec2(1.0f, 1.0f); + + ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); + ImGui::SetNextWindowBgAlpha(0.85f); // semi-transparent + + ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | + ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoFocusOnAppearing | + ImGuiWindowFlags_NoNav; + + if (ImGui::Begin("##Toast", nullptr, flags)) + { + ImGui::TextUnformatted(toast_msg); + } + ImGui::End(); + } +} + +void ui_helper_draw_required_tag() { ImDrawList* draw_list = ImGui::GetWindowDrawList(); diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp index 3115a77..fd9907f 100644 --- a/src/ui/ui_contacts.cpp +++ b/src/ui/ui_contacts.cpp @@ -6,44 +6,51 @@ #include "administration.hpp" #include "locales.hpp" -static view_state current_view_state = LIST; +static view_state current_view_state = view_state::LIST; static contact selected_for_removal; static contact active_contact; -static void draw_contact_form() +void ui_setup_contacts() { - static const char* selected_country = NULL; + current_view_state = view_state::LIST; + memset(&active_contact, 0, sizeof(contact)); + memset(&selected_for_removal, 0, sizeof(contact)); +} - if (ImGui::Button(localize("form.back"))) { - current_view_state = view_state::LIST; - memset(&active_contact, 0, sizeof(contact)); - selected_country = 0; - return; +bool draw_contact_form(contact* buffer, bool back_button_enabled = true, bool viewing_only = false) +{ + const char* selected_country = NULL; + + if (back_button_enabled) + { + if (ImGui::Button(localize("form.back"))) { + current_view_state = view_state::LIST; + selected_country = 0; + return false; + } } ImGui::Spacing(); - bool viewing_only = (current_view_state == view_state::VIEW); - ImGui::BeginDisabled(); float widthAvailable = ImGui::GetContentRegionAvail().x; ImGui::SetNextItemWidth(widthAvailable*0.2f); - ImGui::InputText(localize("contact.form.identifier"), active_contact.id, IM_ARRAYSIZE(active_contact.id)); + ImGui::InputText(localize("contact.form.identifier"), buffer->id, IM_ARRAYSIZE(buffer->id)); if (!viewing_only) ImGui::EndDisabled(); ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.fullname"), localize("contact.form.fullname"), active_contact.name, IM_ARRAYSIZE(active_contact.name)); - ImGui::SameLine();view_draw_required_tag(); + ImGui::InputTextWithHint(localize("contact.form.fullname"), localize("contact.form.fullname"), buffer->name, IM_ARRAYSIZE(buffer->name)); + ImGui::SameLine();ui_helper_draw_required_tag(); ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.address1"), localize("contact.form.address1"), active_contact.address1, IM_ARRAYSIZE(active_contact.address1)); - ImGui::SameLine();view_draw_required_tag(); + ImGui::InputTextWithHint(localize("contact.form.address1"), localize("contact.form.address1"), buffer->address.address1, IM_ARRAYSIZE(buffer->address.address1)); + ImGui::SameLine();ui_helper_draw_required_tag(); ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.address2"), localize("contact.form.address2"), active_contact.address2, IM_ARRAYSIZE(active_contact.address2)); - ImGui::SameLine();view_draw_required_tag(); + ImGui::InputTextWithHint(localize("contact.form.address2"), localize("contact.form.address2"), buffer->address.address2, IM_ARRAYSIZE(buffer->address.address2)); + ImGui::SameLine();ui_helper_draw_required_tag(); ImGui::SetNextItemWidth(widthAvailable*0.5f); @@ -52,7 +59,7 @@ static void draw_contact_form() if (selected_country == 0) { for (int i = 0; i < country_count; i++) { - if (strcmp(countries[i], active_contact.country) == 0) + if (strcmp(countries[i], buffer->address.country) == 0) { selected_country = countries[i]; break; @@ -71,50 +78,43 @@ static void draw_contact_form() ImGui::EndCombo(); } if (selected_country) { - strops_copy(active_contact.country, selected_country, IM_ARRAYSIZE(active_contact.country)); + strops_copy(buffer->address.country, selected_country, IM_ARRAYSIZE(buffer->address.country)); } - ImGui::SameLine();view_draw_required_tag(); + ImGui::SameLine();ui_helper_draw_required_tag(); ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.taxnumber"), localize("contact.form.taxnumber"), active_contact.taxid, IM_ARRAYSIZE(active_contact.taxid)); + ImGui::InputTextWithHint(localize("contact.form.taxnumber"), localize("contact.form.taxnumber"), buffer->taxid, IM_ARRAYSIZE(buffer->taxid)); ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.businessnumber"), localize("contact.form.businessnumber"), active_contact.businessid, IM_ARRAYSIZE(active_contact.businessid)); + ImGui::InputTextWithHint(localize("contact.form.businessnumber"), localize("contact.form.businessnumber"), buffer->businessid, IM_ARRAYSIZE(buffer->businessid)); ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.email"), localize("contact.form.email"), active_contact.email, IM_ARRAYSIZE(active_contact.email)); + ImGui::InputTextWithHint(localize("contact.form.email"), localize("contact.form.email"), buffer->email, IM_ARRAYSIZE(buffer->email)); ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.phonenumber"), localize("contact.form.phonenumber"), active_contact.phone_number, IM_ARRAYSIZE(active_contact.phone_number)); + ImGui::InputTextWithHint(localize("contact.form.phonenumber"), localize("contact.form.phonenumber"), buffer->phone_number, IM_ARRAYSIZE(buffer->phone_number)); ImGui::SetNextItemWidth(widthAvailable*0.5f); - ImGui::InputTextWithHint(localize("contact.form.bankaccount"), localize("contact.form.bankaccount"), active_contact.bank_account, IM_ARRAYSIZE(active_contact.bank_account)); + ImGui::InputTextWithHint(localize("contact.form.bankaccount"), localize("contact.form.bankaccount"), buffer->bank_account, IM_ARRAYSIZE(buffer->bank_account)); if (viewing_only) ImGui::EndDisabled(); if (!viewing_only) { - bool can_save = strlen(active_contact.name) > 0 && strlen(active_contact.address1) > 0 && - strlen(active_contact.address2) > 0 && strlen(active_contact.country) > 0; + bool can_save = strlen(buffer->name) > 0 && strlen(buffer->address.address1) > 0 && + strlen(buffer->address.address2) > 0 && strlen(buffer->address.country) > 0; if (!can_save) ImGui::BeginDisabled(); // Save button ImGui::Spacing(); if (ImGui::Button(localize("form.save"))) { - if (current_view_state == view_state::CREATE) - administration_create_contact(active_contact); - - else if (current_view_state == view_state::EDIT) - administration_update_contact(active_contact); - - memset(&active_contact, 0, sizeof(contact)); - current_view_state = view_state::LIST; - selected_country = 0; + return true; } if (!can_save) ImGui::EndDisabled(); } else { // TODO list invoices connected to contact. } + return false; } static void draw_contact_list() @@ -168,7 +168,7 @@ static void draw_contact_list() ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::Text(c.id); ImGui::TableSetColumnIndex(1); ImGui::Text(c.name); - ImGui::TableSetColumnIndex(2); ImGui::Text("%s %s", c.address1, c.address2); + ImGui::TableSetColumnIndex(2); ImGui::Text("%s %s", c.address.address1, c.address.address2); ImGui::TableSetColumnIndex(3); @@ -221,8 +221,20 @@ void ui_draw_contacts() switch(current_view_state) { case view_state::LIST: draw_contact_list(); break; - case view_state::CREATE: draw_contact_form(); break; - case view_state::EDIT: draw_contact_form(); break; - case view_state::VIEW: draw_contact_form(); break; + case view_state::CREATE: + if (draw_contact_form(&active_contact)) + { + administration_create_contact(active_contact); + current_view_state = view_state::LIST; + } + break; + case view_state::EDIT: + if (draw_contact_form(&active_contact)) + { + administration_update_contact(active_contact); + current_view_state = view_state::LIST; + } + break; + case view_state::VIEW: draw_contact_form(&active_contact, true, true); break; } }
\ No newline at end of file diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp new file mode 100644 index 0000000..ea45f4e --- /dev/null +++ b/src/ui/ui_invoices.cpp @@ -0,0 +1,15 @@ +#include <stdio.h> + +#include "strops.hpp" +#include "ui.hpp" +#include "imgui.h" +#include "administration.hpp" +#include "locales.hpp" + +static view_state current_view_state = LIST; +static invoice active_invoice; + +void ui_draw_invoices() +{ + +}
\ No newline at end of file diff --git a/src/ui/ui_main.cpp b/src/ui/ui_main.cpp index f6661b8..8af8dbc 100644 --- a/src/ui/ui_main.cpp +++ b/src/ui/ui_main.cpp @@ -11,20 +11,38 @@ typedef enum REPORT_RESULTS = 3, REPORT_TAX = 4, PROJECTS = 5, + SETTINGS = 6, END } dashboard_view_state; static dashboard_view_state dashboard_state = dashboard_view_state::INVOICES; void (*drawcalls[dashboard_view_state::END])(void) = { - 0, + ui_draw_invoices, 0, ui_draw_contacts, 0, 0, ui_draw_projects, + ui_draw_settings, }; +void (*setupcalls[dashboard_view_state::END])(void) = { + 0, + 0, + ui_setup_contacts, + 0, + 0, + ui_setup_projects, + ui_setup_settings, +}; + +static void set_dashboard_state(dashboard_view_state state) +{ + dashboard_state = state; + if (setupcalls[dashboard_state]) setupcalls[dashboard_state](); +} + void ui_draw_main() { // @localize @@ -59,21 +77,22 @@ void ui_draw_main() float buttonWidth = sidePanelWidth; - if (ImGui::Button(localize("nav.invoices"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::INVOICES; - if (ImGui::Button(localize("nav.expenses"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::EXPENSES; - if (ImGui::Button(localize("nav.contacts"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::CONTACTS; + if (ImGui::Button(localize("nav.invoices"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::INVOICES); + if (ImGui::Button(localize("nav.expenses"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::EXPENSES); + if (ImGui::Button(localize("nav.contacts"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::CONTACTS); static bool reports_opened = false; if (ImGui::Button(localize("nav.reports"), ImVec2(buttonWidth, 24))) reports_opened = !reports_opened; if (reports_opened) { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20.0f, 0.0f)); - if (ImGui::Button(localize("nav.reports.results"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::REPORT_RESULTS; - if (ImGui::Button(localize("nav.reports.tax"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::REPORT_TAX; + if (ImGui::Button(localize("nav.reports.results"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::REPORT_RESULTS); + if (ImGui::Button(localize("nav.reports.tax"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::REPORT_TAX); ImGui::PopStyleVar(); } - if (ImGui::Button(localize("nav.Projects"), ImVec2(buttonWidth, 24))) dashboard_state = dashboard_view_state::PROJECTS; + if (ImGui::Button(localize("nav.Projects"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::PROJECTS); + if (ImGui::Button("Settings", ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::SETTINGS); //@localize ImGui::PopStyleColor(1); ImGui::PopStyleVar(3); @@ -87,6 +106,7 @@ void ui_draw_main() // Main content ImGui::Begin("AccountingMainWindow", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse); if (drawcalls[dashboard_state]) drawcalls[dashboard_state](); + ui_helper_draw_toasts(); ImGui::End(); // Status bar. diff --git a/src/ui/ui_projects.cpp b/src/ui/ui_projects.cpp index 9490254..a349814 100644 --- a/src/ui/ui_projects.cpp +++ b/src/ui/ui_projects.cpp @@ -5,11 +5,17 @@ #include "administration.hpp" #include "locales.hpp" -static view_state current_view_state = LIST; +static view_state current_view_state = view_state::LIST; static project selected_for_cancellation; static project active_project; +void ui_setup_projects() +{ + current_view_state = view_state::LIST; + memset(&active_project, 0, sizeof(contact)); +} + static void draw_project_form() { static const char* selected_country = NULL; @@ -34,7 +40,7 @@ static void draw_project_form() ImGui::SetNextItemWidth(widthAvailable*0.5f); ImGui::InputTextWithHint(localize("project.form.description"), localize("project.form.description"), active_project.description, IM_ARRAYSIZE(active_project.description)); - ImGui::SameLine();view_draw_required_tag(); + ImGui::SameLine();ui_helper_draw_required_tag(); if (viewing_only) ImGui::EndDisabled(); diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp new file mode 100644 index 0000000..81f6d31 --- /dev/null +++ b/src/ui/ui_settings.cpp @@ -0,0 +1,35 @@ +#include "ui.hpp" +#include "imgui.h" +#include "administration.hpp" +#include "locales.hpp" + +extern bool draw_contact_form(contact* buffer, bool back_button_enabled = true, bool viewing_only = false); + +static contact company_info; +void ui_setup_settings() +{ + company_info = administration_get_company_info(); +} + +void ui_draw_settings() +{ + // @localize + if (ImGui::BeginTabBar("SettingsTabBar", 0)) + { + if (ImGui::BeginTabItem("Company")) + { + bool save = draw_contact_form(&company_info, false); + + if (save) { + administration_set_company_info(company_info); + } + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("VAT Rates")) + { + ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah"); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } +}
\ No newline at end of file |
