aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/browser.cc54
-rw-r--r--src/render/renderer.cc53
2 files changed, 87 insertions, 20 deletions
diff --git a/src/core/browser.cc b/src/core/browser.cc
index e6c63d4..d463b73 100644
--- a/src/core/browser.cc
+++ b/src/core/browser.cc
@@ -379,6 +379,9 @@ InputAction submit_form( const render::InputField& target_input,
std::string body;
for ( const auto& in : inputs ) {
if ( in.action == target_input.action && !in.name.empty() && in.type != "submit" && in.type != "button" ) {
+ if ( ( in.type == "checkbox" || in.type == "radio" ) && !in.checked ) {
+ continue;
+ }
std::string encoded = in.value;
for ( char& ch : encoded ) {
if ( ch == ' ' ) {
@@ -422,6 +425,40 @@ void update_input_value( PageData& page_data, std::size_t index, const std::stri
}
}
+void update_single_line_ui( std::string& line, const std::string& marker, const render::InputField& in )
+{
+ const std::size_t pos = line.find( marker );
+ if ( pos == std::string::npos ) {
+ return;
+ }
+ const std::size_t end = line.find( ']', pos );
+ if ( end == std::string::npos ) {
+ return;
+ }
+
+ std::string prefix;
+ if ( in.type == "checkbox" ) {
+ prefix = in.checked ? "[X] " : "[ ] ";
+ } else {
+ prefix = in.checked ? "(X) " : "( ) ";
+ }
+ line.replace( pos, end - pos + 1, marker + prefix + in.value + "]" );
+}
+
+void update_toggle_ui( PageData& page_data )
+{
+ for ( std::size_t i = 0; i < page_data.inputs.size(); ++i ) {
+ const auto& in = page_data.inputs[i];
+ if ( in.type != "checkbox" && in.type != "radio" ) {
+ continue;
+ }
+ const std::string marker = "[I" + std::to_string( i + 1 ) + ":";
+ for ( auto& line : page_data.lines ) {
+ update_single_line_ui( line, marker, in );
+ }
+ }
+}
+
InputAction handle_form_input( const tui::Terminal& terminal,
PageData& page_data,
const std::string& current_url,
@@ -442,11 +479,26 @@ InputAction handle_form_input( const tui::Terminal& terminal,
return InputAction::None;
}
- const auto& target_input = page_data.inputs[index - 1];
+ auto& target_input = page_data.inputs[index - 1];
if ( target_input.type == "submit" || target_input.type == "button" ) {
return submit_form( target_input, page_data.inputs, current_url, history, history_idx );
}
+ if ( target_input.type == "checkbox" || target_input.type == "radio" ) {
+ if ( target_input.type == "radio" ) {
+ for ( auto& in : page_data.inputs ) {
+ if ( in.name == target_input.name && in.action == target_input.action ) {
+ in.checked = false;
+ }
+ }
+ target_input.checked = true;
+ } else {
+ target_input.checked = !target_input.checked;
+ }
+ update_toggle_ui( page_data );
+ return InputAction::None;
+ }
+
const std::string query = get_terminal_input( terminal, "Enter Text [I" + std::to_string( index ) + "]:" );
if ( query.empty() ) {
return InputAction::None;
diff --git a/src/render/renderer.cc b/src/render/renderer.cc
index 4b152b7..3744728 100644
--- a/src/render/renderer.cc
+++ b/src/render/renderer.cc
@@ -71,25 +71,35 @@ std::string decode_entities( std::string text )
std::string extract_attr( const std::string& tag_name, std::string_view attr_name )
{
- std::string match = std::string( attr_name ) + "=\"";
+ std::string match = " " + std::string( attr_name ) + "=";
std::size_t pos = tag_name.find( match );
- if ( pos != std::string::npos ) {
- pos += match.length();
- const std::size_t end = tag_name.find( '"', pos );
- if ( end != std::string::npos ) {
- return tag_name.substr( pos, end - pos );
+
+ if ( pos == std::string::npos ) {
+ match = std::string( attr_name ) + "=";
+ if ( !tag_name.starts_with( match ) ) {
+ return "";
}
+ pos = 0;
+ } else {
+ pos += 1;
+ }
+
+ pos += attr_name.length() + 1;
+ if ( pos >= tag_name.length() ) {
+ return "";
}
- match = std::string( attr_name ) + "='";
- pos = tag_name.find( match );
- if ( pos != std::string::npos ) {
- pos += match.length();
- const std::size_t end = tag_name.find( '\'', pos );
+
+ const char quote = tag_name[pos];
+ if ( quote == '"' || quote == '\'' ) {
+ const std::size_t end = tag_name.find( quote, pos + 1 );
if ( end != std::string::npos ) {
- return tag_name.substr( pos, end - pos );
+ return tag_name.substr( pos + 1, end - pos - 1 );
}
+ return "";
}
- return "";
+
+ const std::size_t end = tag_name.find_first_of( " >/", pos );
+ return tag_name.substr( pos, ( end == std::string::npos ) ? std::string::npos : end - pos );
}
void render_link_end( const parser::DomNode& node, RenderResult& result )
@@ -114,10 +124,10 @@ void render_img( const parser::DomNode& node, RenderResult& result )
}
}
-std::string build_input_hint( const std::string& tag_name )
+std::string build_input_hint( const std::string& tag_name, bool checked )
{
std::string placeholder = extract_attr( tag_name, "placeholder" );
- std::string type = extract_attr( tag_name, "type" );
+ const std::string type = extract_attr( tag_name, "type" );
std::string val = extract_attr( tag_name, "value" );
if ( !placeholder.empty() ) {
@@ -126,8 +136,11 @@ std::string build_input_hint( const std::string& tag_name )
if ( type == "submit" || type == "button" ) {
return val.empty() ? "Submit" : val;
}
- if ( type == "checkbox" || type == "radio" ) {
- return type;
+ if ( type == "checkbox" ) {
+ return checked ? "[X] " + val : "[ ] " + val;
+ }
+ if ( type == "radio" ) {
+ return checked ? "(X) " + val : "( ) " + val;
}
if ( type == "hidden" ) {
return "hidden";
@@ -167,9 +180,11 @@ void render_input_node( const parser::DomNode& node,
type = "submit";
}
const std::string default_val = extract_attr( node.tag_name, "value" );
- result.inputs.push_back( { extract_attr( node.tag_name, "name" ), ctx.action, ctx.method, default_val, type } );
+ const bool is_checked = node.tag_name.contains( "checked" );
+ result.inputs.push_back(
+ { extract_attr( node.tag_name, "name" ), ctx.action, ctx.method, default_val, type, is_checked } );
- std::string hint = build_input_hint( node.tag_name );
+ std::string hint = build_input_hint( node.tag_name, is_checked );
if ( base_tag == "button" ) {
hint = "Submit";
}