From 33e0530f4ffb827045ccbfc8b7fba23f5300dd84 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Thu, 19 Dec 2024 09:49:50 -0300 Subject: [PATCH 01/20] enable nix for everything --- .github/workflows/nix-build.yml | 34 +++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 13c719874b..059efb15c6 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -1,21 +1,23 @@ name: Nix Build -on: - workflow_dispatch: - pull_request: - branches: - - main - paths: - - '**/*.rs' - - '.github/workflows/nix-build.yml' - - 'nix/**' - push: - branches: - - main - paths: - - '**/*.rs' - - '.github/workflows/nix-build.yml' - - 'nix/**' +on: [push, pull_request] + +# on: +# workflow_dispatch: +# pull_request: +# branches: +# - main +# paths: +# - '**/*.rs' +# - '.github/workflows/nix-build.yml' +# - 'nix/**' +# push: +# branches: +# - main +# paths: +# - '**/*.rs' +# - '.github/workflows/nix-build.yml' +# - 'nix/**' jobs: lints: From 964b11c3624f34914ce9f5a8f16183e84eb84305 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Thu, 19 Dec 2024 09:53:12 -0300 Subject: [PATCH 02/20] ok my first guess is that resizing fn is actually the culpirit --- frontends/rioterm/src/context/grid.rs | 5228 ++++++++++++------------- frontends/rioterm/src/context/mod.rs | 370 +- 2 files changed, 2799 insertions(+), 2799 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index de49be4807..f9189bd42e 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -969,2618 +969,2618 @@ pub mod test { use pretty_assertions::assert_eq; use rio_window::window::WindowId; - #[test] - fn test_single_context_respecting_margin_and_no_quad_creation() { - let margin = Delta { - x: 10., - top_y: 20., - bottom_y: 20., - }; - - let context_dimension = ContextDimension::build( - 1200.0, - 800.0, - SugarDimensions { - scale: 2., - width: 18., - height: 9., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 66); - assert_eq!(context_dimension.lines, 88); - let rich_text_id = 1; - let route_id = 0; - let context = create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ); - let context_width = context.dimension.width; - let context_height = context.dimension.height; - let context_margin = context.dimension.margin; - let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); - // The first context should fill completely w/h grid - assert_eq!(grid.width, context_width); - assert_eq!(grid.height, context_height); - - // Context margin should empty - assert_eq!(Delta::::default(), context_margin); - assert_eq!(grid.margin, margin); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: rich_text_id, - position: [10., 20.], - })] - ); - } - - #[test] - fn test_split_right() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 1200.0, - 800.0, - SugarDimensions { - scale: 1., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 85); - assert_eq!(context_dimension.lines, 100); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - grid.split_right(second_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - Object::RichText(RichText { - id: second_context_id, - position: [600., 0.0] - }), - create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - ] - ); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - Object::RichText(RichText { - id: second_context_id, - position: [600.0, 0.0] - }), - create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), - Object::RichText(RichText { - id: third_context_id, - position: [900.0, 0.0] - }), - create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - ] - ); - } - - #[test] - fn test_split_right_with_margin() { - let margin = Delta { - x: 20., - top_y: 30., - bottom_y: 40., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - })] - ); - grid.split_right(second_context); - - /* - > before split: - 20 (600/20) - |------| - - Available width should compute with margin - so should be 600 - 20 = 580, then will be: - 289 + 4 (PADDING) + 290 - - > after split: - 10 (289/0) (4) (290/10) - |----------|----------| - - Margin should be splitted between first columns - items and last columns items - */ - - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 290.); - assert_eq!(contexts[1].val.dimension.margin.x, 10.); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - }), - create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: second_context_id, - position: [167.0, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [145.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [312.0, margin.top_y], [1.0, 300.0]), - ] - ); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - }), - create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: second_context_id, - position: [167.0, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [65.5, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [232.5, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: third_context_id, - position: [236.5, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [236.5, 330.0], [67.5, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [304.0, margin.top_y], [1.0, 300.0]), - ] - ); - - // Last context should be updated with half of x - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 131.); - assert_eq!(contexts[1].val.dimension.margin.x, 0.); - assert_eq!(contexts[2].val.dimension.width, 135.); - assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.select_prev_split(); - grid.split_right(fourth_context); - - // If the split right happens in not the last - // then should not update margin to half of x - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 51.5); - assert_eq!(contexts[1].val.dimension.margin.x, 0.); - assert_eq!(contexts[3].val.dimension.width, 55.5); - assert_eq!(contexts[3].val.dimension.margin.x, 0.); - - // 2 is the last one - assert_eq!(contexts[2].val.dimension.width, 135.0); - assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - }), - create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: second_context_id, - position: [167.0, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [25.75, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: fourth_context_id, - position: [196.75, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.0], [27.75, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: third_context_id, - position: [228.5, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.0], [67.5, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), - ] - ); - } - - #[test] - fn test_split_right_with_margin_inside_parent() { - let margin = Delta { - x: 20., - top_y: 30., - bottom_y: 40., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - })] - ); - - let (third_context, _third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, _fourth_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fifth_context, _fifth_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(second_context); - grid.select_prev_split(); - grid.split_down(third_context); - grid.split_right(fourth_context); - grid.split_right(fifth_context); - - // If the split right happens in not the last - // then should not update margin to half of x - - assert_eq!(grid.current_index(), 4); - - // |1.--------------|2.------------| - // |3.----|4.--|5.--|--------------| - let contexts = grid.contexts(); - assert_eq!(contexts.len(), 5); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 290.); - assert_eq!(contexts[1].val.dimension.margin.x, 10.); - assert_eq!(contexts[2].val.dimension.width, 129.0); - assert_eq!(contexts[2].val.dimension.margin.x, 0.); - assert_eq!(contexts[3].val.dimension.width, 52.5); - assert_eq!(contexts[3].val.dimension.margin.x, 0.); - assert_eq!(contexts[4].val.dimension.width, 56.5); - - // Fifth context should not have any margin x - // TODO: - // assert_eq!(contexts[4].val.dimension.margin.x, 0.); - - grid.remove_current(); - assert_eq!(grid.current_index(), 3); - let contexts = grid.contexts(); - assert_eq!(contexts[1].val.dimension.margin.x, 10.); - // Fourth context should not have any margin x - // TODO: - // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - } - - #[test] - fn test_split_down_with_margin_inside_parent() { - let margin = Delta { - x: 20., - top_y: 30., - bottom_y: 40., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 1., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (third_context, third_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 4; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fifth_context, fifth_context_id) = { - let rich_text_id = 5; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - })] - ); - - grid.split_down(second_context); - grid.split_down(third_context); - grid.split_right(fourth_context); - grid.select_prev_split(); - grid.select_prev_split(); - let current_index = grid.current_index(); - let contexts = grid.contexts(); - assert_eq!(contexts[current_index].val.rich_text_id, second_context_id); - grid.split_right(fifth_context); - - // If the split right happens in not the last - // then should not update margin to half of x - - assert_eq!(grid.current_index(), 4); - - // |1.--------------| - // |2.------|5.-----| - // |3.------|4.-----| - let contexts = grid.contexts(); - assert_eq!(contexts.len(), 5); - - assert_eq!(contexts[0].val.rich_text_id, first_context_id); - assert_eq!(contexts[0].val.dimension.height, 298.); - assert_eq!(contexts[0].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[0].val.dimension.margin.bottom_y, 0.); - let first_down = contexts[0].down; - assert_eq!(first_down, Some(1)); - assert_eq!( - contexts[first_down.unwrap_or_default()].val.rich_text_id, - second_context_id - ); - - assert_eq!(contexts[1].val.rich_text_id, second_context_id); - assert_eq!(contexts[1].val.dimension.height, 148.); - assert_eq!(contexts[1].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[1].val.dimension.margin.bottom_y, 0.); - - assert_eq!(contexts[4].val.rich_text_id, fifth_context_id); - assert_eq!(contexts[4].val.dimension.height, 148.0); - assert_eq!(contexts[4].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[4].val.dimension.margin.bottom_y, 0.); - - assert_eq!(contexts[2].val.rich_text_id, third_context_id); - assert_eq!(contexts[2].val.dimension.height, 150.0); - assert_eq!(contexts[2].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[2].val.dimension.margin.bottom_y, 40.); - - assert_eq!(contexts[3].val.rich_text_id, fourth_context_id); - assert_eq!(contexts[3].val.dimension.height, 150.0); - assert_eq!(contexts[3].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[3].val.dimension.margin.bottom_y, 40.); - - // Fifth context should not have any margin x - // TODO: Removal - // grid.remove_current(); - } - - #[test] - // https://github.com/raphamorim/rio/issues/760 - fn test_split_issue_760() { - let width = 1200.; - let height = 800.; - - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - width, - height, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 85); - assert_eq!(context_dimension.lines, 100); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - grid.split_down(second_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - Object::RichText(RichText { - id: second_context_id, - position: [0.0, 202.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - ] - ); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, first_context_id); - assert_eq!(grid.current_index(), 0); - grid.split_right(third_context); - assert_eq!(grid.current().rich_text_id, third_context_id); - assert_eq!(grid.current_index(), 2); - - let contexts = grid.contexts(); - - let scaled_padding = PADDING * contexts[0].val.dimension.dimension.scale; - - // Check their respective width - assert_eq!( - contexts[0].val.dimension.width, - (width / 2.) - scaled_padding - ); - assert_eq!(contexts[1].val.dimension.width, width); - assert_eq!(contexts[2].val.dimension.width, width / 2.); - - // Check their respective height - let top_height = (height / 2.) - scaled_padding; - assert_eq!(contexts[0].val.dimension.height, top_height); - assert_eq!(contexts[1].val.dimension.height, height / 2.); - assert_eq!(contexts[2].val.dimension.height, top_height); - - // [RichText(RichText { id: 0, position: [0.0, 0.0] }), - // Rect(Rect { position: [298.0, 0.0], color: [0.0, 0.0, 1.0, 0.0], size: [1.0, 396.0] }), - // RichText(RichText { id: 2, position: [302.0, 0.0] }), - // Rect(Rect { position: [0.0, 198.0], color: [0.0, 0.0, 1.0, 0.0], size: [596.0, 1.0] }), - // RichText(RichText { id: 1, position: [0.0, 202.0] })] - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [298.0, 1.0]), - Object::RichText(RichText { - id: second_context_id, - position: [0.0, 202.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - create_border([0.0, 0.0, 1.0, 0.0], [298.0, 0.0], [1.0, 198.0]), - Object::RichText(RichText { - id: third_context_id, - position: [302.0, 0.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [302.0, 198.0], [300.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [602.0, 0.0], [1.0, 198.0]), - ] - ); - } - - #[test] - fn test_remove_right_with_margin() { - let margin = Delta { - x: 20., - top_y: 30., - bottom_y: 40., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - })] - ); - grid.split_right(second_context); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - - let first_expected_dimension = (286., 0.); - let second_expected_dimension = (131., 0.); - let third_expected_dimension = (135., 10.); - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); - assert_eq!( - contexts[0].val.dimension.margin.x, - first_expected_dimension.1 - ); - assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); - assert_eq!( - contexts[1].val.dimension.margin.x, - second_expected_dimension.1 - ); - assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); - assert_eq!( - contexts[2].val.dimension.margin.x, - third_expected_dimension.1 - ); - - grid.select_prev_split(); - grid.split_right(fourth_context); - - // If the split right happens in not the last - // then should not update margin to half of x - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 51.5); - assert_eq!(contexts[1].val.dimension.margin.x, 0.); - assert_eq!(contexts[3].val.dimension.width, 55.5); - assert_eq!(contexts[3].val.dimension.margin.x, 0.); - - // 2 is the last one - assert_eq!(contexts[2].val.dimension.width, 135.0); - assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - }), - create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.], [143.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: second_context_id, - position: [167.0, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.], [25.75, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: fourth_context_id, - position: [196.75, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.], [27.75, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: third_context_id, - position: [228.5, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.], [67.5, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), - ] - ); - - grid.remove_current(); - - // If the split right happens in not the last - // then should not update margin to half of x - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); - assert_eq!( - contexts[0].val.dimension.margin.x, - first_expected_dimension.1 - ); - assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); - assert_eq!( - contexts[1].val.dimension.margin.x, - second_expected_dimension.1 - ); - assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); - assert_eq!( - contexts[2].val.dimension.margin.x, - third_expected_dimension.1 - ); - - assert_eq!(grid.current_index(), 1); - grid.select_next_split(); - assert_eq!(grid.current_index(), 2); - - // Margin x should move to last - grid.remove_current(); - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 290.); - assert_eq!(contexts[1].val.dimension.margin.x, 10.); - } - - #[test] - fn test_split_down() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 1200.0, - 800.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 85); - assert_eq!(context_dimension.lines, 100); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - grid.split_down(second_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - Object::RichText(RichText { - id: second_context_id, - position: [0.0, 202.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - ] - ); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_down(third_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - Object::RichText(RichText { - id: second_context_id, - position: [0.0, 202.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 300.0], [600.0, 1.0]), - Object::RichText(RichText { - id: third_context_id, - position: [0.0, 304.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 404.0], [600.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 304.0], [1.0, 100.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 98.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - ] - ); - } - - #[test] - fn test_resize() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (third_context, _third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_right(second_context); - grid.split_down(third_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // Object::Rect(Rect { - // position: [147.0, 0.0], - // color: [0.0, 0.0, 0.0, 0.0], - // size: [1.0, 300.0] - // }), - // Object::RichText(RichText { - // id: second_context_id, - // position: [149.0, 0.0] - // }), - // Object::Rect(Rect { - // position: [149.0, 147.0], - // color: [0.0, 0.0, 0.0, 0.0], - // size: [294.0, 1.0] - // }), - // Object::RichText(RichText { - // id: third_context_id, - // position: [149.0, 149.0] - // }), - // ] - // ); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - grid.resize(1200.0, 600.0); - - // TODO: Finish test - } - - #[test] - fn test_remove_right_without_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - assert_eq!(grid.current().dimension.width, 600.); - - grid.split_right(second_context); - - let new_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.width, new_expected_width); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - let old_expected_width = (600. / 2.) - scaled_padding; - assert_eq!(grid.current().dimension.width, old_expected_width); - assert_eq!(grid.current_index(), 0); - - grid.select_next_split(); - assert_eq!(grid.current_index(), 1); - - grid.remove_current(); - - assert_eq!(grid.current_index(), 0); - // Whenever return to one should drop padding - assert_eq!(grid.current().dimension.width, 600.); - } - - #[test] - fn test_remove_right_with_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_right(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - let old_context_expected_width = (600. / 2.) - scaled_padding; - assert_eq!(grid.current().dimension.width, old_context_expected_width); - assert_eq!(grid.current_index(), 0); - - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].right, Some(1)); - assert_eq!(grid.contexts()[current_index].down, None); - - grid.remove_current(); - - assert_eq!(grid.current_index(), 0); - // Whenever return to one should drop padding - let expected_width = 600.; - assert_eq!(grid.current().dimension.width, expected_width); - - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].right, None); - assert_eq!(grid.contexts()[current_index].down, None); - } - - #[test] - fn test_remove_right_with_down_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_right(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current_index(), 1); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_down(third_context); - assert_eq!(grid.current_index(), 2); - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current().dimension.height, 300.); - - // Move back - grid.select_prev_split(); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, second_context_id); - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current().dimension.height, 296.); - - // Remove the current should actually make right being down - grid.remove_current(); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, third_context_id); - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current().dimension.height, 600.); - } - - #[test] - fn test_remove_down_without_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - assert_eq!(grid.current().dimension.width, 600.); - - grid.split_down(second_context); - - let new_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_expected_width); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - let old_expected_width = (600. / 2.) - scaled_padding; - assert_eq!(grid.current().dimension.height, old_expected_width); - assert_eq!(grid.current_index(), 0); - - grid.select_next_split(); - assert_eq!(grid.current_index(), 1); - - grid.remove_current(); - - assert_eq!(grid.current_index(), 0); - // Whenever return to one should drop padding - assert_eq!(grid.current().dimension.height, 600.); - } - - #[test] - fn test_remove_down_with_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_down(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_height = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - let old_context_expected_height = (600. / 2.) - scaled_padding; - assert_eq!(grid.current().dimension.height, old_context_expected_height); - assert_eq!(grid.current_index(), 0); - - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].down, Some(1)); - assert_eq!(grid.contexts()[current_index].right, None); - - grid.remove_current(); - - assert_eq!(grid.current_index(), 0); - // Whenever return to one should drop padding - let expected_height = 600.; - assert_eq!(grid.current().dimension.height, expected_height); - - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].down, None); - assert_eq!(grid.contexts()[current_index].right, None); - } - - #[test] - fn test_remove_down_with_right_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_down(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_height = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current_index(), 1); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - assert_eq!(grid.current_index(), 2); - assert_eq!(grid.current().dimension.width, new_context_expected_height); - assert_eq!(grid.current().dimension.height, 300.); - - // Move back - grid.select_prev_split(); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, second_context_id); - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current().dimension.width, 296.); - - // Remove the current should actually make down being down - grid.remove_current(); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, third_context_id); - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current().dimension.width, 600.); - } - - #[test] - fn test_remove_context_with_parent_but_down_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (third_context, third_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 4; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fifth_context, fifth_context_id) = { - let rich_text_id = 5; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (sixth_context, sixth_context_id) = { - let rich_text_id = 6; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - // The test is to validate the removal of a context with parenting however - // should move to up the down items - // - // Test setup - // - // |1.-----|.3-----|4.-----| - // |2.-----|.5-|6.-|-------| - - grid.split_down(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_height = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current().rich_text_id, second_context_id); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, first_context_id); - - grid.split_right(third_context); - assert_eq!(grid.current().rich_text_id, third_context_id); - - grid.split_right(fourth_context); - assert_eq!(grid.current().rich_text_id, fourth_context_id); - - let current_index = grid.current_index(); - assert_eq!(current_index, 3); - assert_eq!(grid.contexts()[current_index].down, None); - - // So far we have: - // - // |1.-----|.3-----|4.-----| - // |2.-----|-------|-------| - - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, third_context_id); - let current_index = grid.current_index(); - assert_eq!(current_index, 2); - assert_eq!(grid.contexts()[current_index].down, None); - - grid.split_down(fifth_context); - assert_eq!(grid.current().rich_text_id, fifth_context_id); - - grid.split_right(sixth_context); - assert_eq!(grid.current().rich_text_id, sixth_context_id); - - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - - assert_eq!(grid.current().rich_text_id, third_context_id); - - let current_index = grid.current_index(); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - fourth_context_id - ); - let current_index = grid.current_index(); - let down = grid.contexts()[current_index].down; - assert_eq!( - grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - fifth_context_id - ); - // Setup complete, now we have 3 as active as well - // - // |1.-----|.3-----|4.-----| - // |2.-----|.5-|6.-|-------| - // - // If we remove 3 then should be - // - // |1.-----|.5-|6.-|4.-----| - // |2.-----|---|---|-------| - - grid.remove_current(); - - // Check if current is 5 and next is 6 - assert_eq!(grid.current().rich_text_id, fifth_context_id); - let current_index = grid.current_index(); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - sixth_context_id - ); - - // Let's go back to 1 to check if leads to 5 - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - - assert_eq!(grid.current().rich_text_id, first_context_id); - let current_index = grid.current_index(); - assert_eq!(current_index, 0); - let right = grid.contexts()[current_index].right; - assert_eq!(right, Some(3)); - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - fifth_context_id - ); - - // Let's go to 6 to check if leads to 4 - // - // |1.-----|.5-|6.-|4.-----| - // |2.-----|---|---|-------| - - grid.select_next_split(); - grid.select_next_split(); - grid.select_next_split(); - grid.select_next_split(); - - assert_eq!(grid.current().rich_text_id, sixth_context_id); - let current_index = grid.current_index(); - let right = grid.contexts()[current_index].right; - assert_eq!(right, Some(2)); - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - fourth_context_id - ); - } - - #[test] - fn test_remove_context_without_parents_but_with_right_and_down_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (third_context, third_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 4; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_right(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current().rich_text_id, second_context_id); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, second_context_id); - - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, first_context_id); - - grid.split_down(third_context); - assert_eq!(grid.current().rich_text_id, third_context_id); - assert_eq!(grid.current().dimension.width, 296.); - assert_eq!(grid.current().dimension.height, 300.); - - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, second_context_id); - grid.split_down(fourth_context); - - assert_eq!(grid.current_index(), 3); - assert_eq!(grid.current().rich_text_id, fourth_context_id); - - grid.select_next_split(); - assert_eq!(grid.current_index(), 0); - assert_eq!(grid.current().rich_text_id, first_context_id); - - // Active is 1 - // |1.----|.2----| - // |3.----|.4----| - - // Remove the current should actually make right being down - grid.remove_current(); - let current_index = grid.current_index(); - // Move third context to first position - assert_eq!(current_index, 0); - assert_eq!(grid.current().rich_text_id, third_context_id); - let right = grid.contexts()[current_index].right; - let right_context = grid.contexts()[right.unwrap_or_default()].val.rich_text_id; - assert_eq!(right_context, second_context_id); - - // Result: - // |3.----|.2----| - // |------|.4----| - - // Now let's create a more complex case - // |3.---------|.2---------| - // |5.-|6.-|7.-|.4---------| - - let (fifth_context, fifth_context_id) = { - let rich_text_id = 5; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (sixth_context, sixth_context_id) = { - let rich_text_id = 6; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (seventh_context, seventh_context_id) = { - let rich_text_id = 7; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_down(fifth_context); - grid.split_right(sixth_context); - grid.split_right(seventh_context); - - assert_eq!(grid.current_index(), 5); - assert_eq!(grid.current().rich_text_id, seventh_context_id); - - // Current: - // |3.---------|.2---------| - // |5.-|6.-|7.-|.4---------| - // - // Now if we move back to 3. and remove it: - // Should move 5, 6 and 7 to top. - // - // |5.-|6.-|7.-|.2---------| - // |---|---|---|.4---------| - grid.select_next_split(); - assert_eq!(grid.current().rich_text_id, third_context_id); - let current_index = grid.current_index(); - let down = grid.contexts()[current_index].down; - assert_eq!( - grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - fifth_context_id - ); - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, fifth_context_id); - - let current_index = grid.current_index(); - let right = grid.contexts()[current_index].right.unwrap_or_default(); - let right_context = &grid.contexts()[right]; - assert_eq!(right_context.val.rich_text_id, sixth_context_id); - - // Current: - // |5.-|6.-|7.-|.2---------| - // |---|---|---|.4---------| - - // Ok, let's test the reverse to right operations - // First remove 5 and 6 - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, sixth_context_id); - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].down, None); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - seventh_context_id - ); - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, seventh_context_id); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - second_context_id - ); - - // Current: - // |7.---------|.2---------| - // |-----------|.4---------| - - // Now let's add many 5 and 6 as down items on 7th - // - // Should be: - // |7.---------|.2---------| - // |5.---------|.4---------| - // |6.---------|-----------| - - let (fifth_context, fifth_context_id) = { - let rich_text_id = 5; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (sixth_context, sixth_context_id) = { - let rich_text_id = 6; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_down(fifth_context); - grid.split_down(sixth_context); - - assert_eq!(grid.current().rich_text_id, sixth_context_id); - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, fifth_context_id); - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, seventh_context_id); - - // Next step remove 7 - // - // Should be: - // |5.---------|.2---------| - // |6.---------|.4---------| - // |-----------|-----------| - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, fifth_context_id); - let right = grid.contexts()[current_index].right; - let down = grid.contexts()[current_index].down; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - second_context_id - ); - assert_eq!( - grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - sixth_context_id - ); - - // Next step remove 5 - // - // Should be: - // |6.---------|.2---------| - // |-----------|.4---------| - // |-----------|-----------| - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, sixth_context_id); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - second_context_id - ); - assert_eq!(grid.contexts()[current_index].down, None); - } - - #[test] - fn test_select_current_based_on_mouse() { - let mut mouse = Mouse::default(); - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.select_current_based_on_mouse(&mouse); - // On first should always return first item - assert_eq!(grid.current_index(), 0); - - grid.split_down(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_height = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current_index(), 1); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - assert_eq!(grid.current_index(), 2); - assert_eq!(grid.current().dimension.width, new_context_expected_height); - assert_eq!(grid.current().dimension.height, 300.); - - grid.select_current_based_on_mouse(&mouse); - assert_eq!(grid.current_index(), 0); - assert_eq!(grid.current().rich_text_id, 0); - - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - mouse.y = (new_context_expected_height + scaled_padding) as usize; - grid.select_current_based_on_mouse(&mouse); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, second_context_id); - - mouse.x = 304; - grid.select_current_based_on_mouse(&mouse); - - assert_eq!(grid.current_index(), 2); - assert_eq!(grid.current().rich_text_id, third_context_id); - } + // #[test] + // fn test_single_context_respecting_margin_and_no_quad_creation() { + // let margin = Delta { + // x: 10., + // top_y: 20., + // bottom_y: 20., + // }; + + // let context_dimension = ContextDimension::build( + // 1200.0, + // 800.0, + // SugarDimensions { + // scale: 2., + // width: 18., + // height: 9., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 66); + // assert_eq!(context_dimension.lines, 88); + // let rich_text_id = 1; + // let route_id = 0; + // let context = create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ); + // let context_width = context.dimension.width; + // let context_height = context.dimension.height; + // let context_margin = context.dimension.margin; + // let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); + // // The first context should fill completely w/h grid + // assert_eq!(grid.width, context_width); + // assert_eq!(grid.height, context_height); + + // // Context margin should empty + // assert_eq!(Delta::::default(), context_margin); + // assert_eq!(grid.margin, margin); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: rich_text_id, + // position: [10., 20.], + // })] + // ); + // } + + // #[test] + // fn test_split_right() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 1200.0, + // 800.0, + // SugarDimensions { + // scale: 1., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 85); + // assert_eq!(context_dimension.lines, 100); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + // grid.split_right(second_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [600., 0.0] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + // ] + // ); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [600.0, 0.0] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [900.0, 0.0] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + // ] + // ); + // } + + // #[test] + // fn test_split_right_with_margin() { + // let margin = Delta { + // x: 20., + // top_y: 30., + // bottom_y: 40., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // })] + // ); + // grid.split_right(second_context); + + // /* + // > before split: + // 20 (600/20) + // |------| + + // Available width should compute with margin + // so should be 600 - 20 = 580, then will be: + // 289 + 4 (PADDING) + 290 + + // > after split: + // 10 (289/0) (4) (290/10) + // |----------|----------| + + // Margin should be splitted between first columns + // items and last columns items + // */ + + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 290.); + // assert_eq!(contexts[1].val.dimension.margin.x, 10.); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [167.0, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [145.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [312.0, margin.top_y], [1.0, 300.0]), + // ] + // ); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [167.0, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [65.5, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [232.5, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [236.5, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [236.5, 330.0], [67.5, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [304.0, margin.top_y], [1.0, 300.0]), + // ] + // ); + + // // Last context should be updated with half of x + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 131.); + // assert_eq!(contexts[1].val.dimension.margin.x, 0.); + // assert_eq!(contexts[2].val.dimension.width, 135.); + // assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.select_prev_split(); + // grid.split_right(fourth_context); + + // // If the split right happens in not the last + // // then should not update margin to half of x + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 51.5); + // assert_eq!(contexts[1].val.dimension.margin.x, 0.); + // assert_eq!(contexts[3].val.dimension.width, 55.5); + // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + + // // 2 is the last one + // assert_eq!(contexts[2].val.dimension.width, 135.0); + // assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [167.0, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [25.75, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: fourth_context_id, + // position: [196.75, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.0], [27.75, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [228.5, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.0], [67.5, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), + // ] + // ); + // } + + // #[test] + // fn test_split_right_with_margin_inside_parent() { + // let margin = Delta { + // x: 20., + // top_y: 30., + // bottom_y: 40., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // })] + // ); + + // let (third_context, _third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, _fourth_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fifth_context, _fifth_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(second_context); + // grid.select_prev_split(); + // grid.split_down(third_context); + // grid.split_right(fourth_context); + // grid.split_right(fifth_context); + + // // If the split right happens in not the last + // // then should not update margin to half of x + + // assert_eq!(grid.current_index(), 4); + + // // |1.--------------|2.------------| + // // |3.----|4.--|5.--|--------------| + // let contexts = grid.contexts(); + // assert_eq!(contexts.len(), 5); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 290.); + // assert_eq!(contexts[1].val.dimension.margin.x, 10.); + // assert_eq!(contexts[2].val.dimension.width, 129.0); + // assert_eq!(contexts[2].val.dimension.margin.x, 0.); + // assert_eq!(contexts[3].val.dimension.width, 52.5); + // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + // assert_eq!(contexts[4].val.dimension.width, 56.5); + + // // Fifth context should not have any margin x + // // TODO: + // // assert_eq!(contexts[4].val.dimension.margin.x, 0.); + + // grid.remove_current(); + // assert_eq!(grid.current_index(), 3); + // let contexts = grid.contexts(); + // assert_eq!(contexts[1].val.dimension.margin.x, 10.); + // // Fourth context should not have any margin x + // // TODO: + // // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + // } + + // #[test] + // fn test_split_down_with_margin_inside_parent() { + // let margin = Delta { + // x: 20., + // top_y: 30., + // bottom_y: 40., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 1., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (third_context, third_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 4; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fifth_context, fifth_context_id) = { + // let rich_text_id = 5; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // })] + // ); + + // grid.split_down(second_context); + // grid.split_down(third_context); + // grid.split_right(fourth_context); + // grid.select_prev_split(); + // grid.select_prev_split(); + // let current_index = grid.current_index(); + // let contexts = grid.contexts(); + // assert_eq!(contexts[current_index].val.rich_text_id, second_context_id); + // grid.split_right(fifth_context); + + // // If the split right happens in not the last + // // then should not update margin to half of x + + // assert_eq!(grid.current_index(), 4); + + // // |1.--------------| + // // |2.------|5.-----| + // // |3.------|4.-----| + // let contexts = grid.contexts(); + // assert_eq!(contexts.len(), 5); + + // assert_eq!(contexts[0].val.rich_text_id, first_context_id); + // assert_eq!(contexts[0].val.dimension.height, 298.); + // assert_eq!(contexts[0].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[0].val.dimension.margin.bottom_y, 0.); + // let first_down = contexts[0].down; + // assert_eq!(first_down, Some(1)); + // assert_eq!( + // contexts[first_down.unwrap_or_default()].val.rich_text_id, + // second_context_id + // ); + + // assert_eq!(contexts[1].val.rich_text_id, second_context_id); + // assert_eq!(contexts[1].val.dimension.height, 148.); + // assert_eq!(contexts[1].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[1].val.dimension.margin.bottom_y, 0.); + + // assert_eq!(contexts[4].val.rich_text_id, fifth_context_id); + // assert_eq!(contexts[4].val.dimension.height, 148.0); + // assert_eq!(contexts[4].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[4].val.dimension.margin.bottom_y, 0.); + + // assert_eq!(contexts[2].val.rich_text_id, third_context_id); + // assert_eq!(contexts[2].val.dimension.height, 150.0); + // assert_eq!(contexts[2].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[2].val.dimension.margin.bottom_y, 40.); + + // assert_eq!(contexts[3].val.rich_text_id, fourth_context_id); + // assert_eq!(contexts[3].val.dimension.height, 150.0); + // assert_eq!(contexts[3].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[3].val.dimension.margin.bottom_y, 40.); + + // // Fifth context should not have any margin x + // // TODO: Removal + // // grid.remove_current(); + // } + + // #[test] + // // https://github.com/raphamorim/rio/issues/760 + // fn test_split_issue_760() { + // let width = 1200.; + // let height = 800.; + + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // width, + // height, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 85); + // assert_eq!(context_dimension.lines, 100); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + // grid.split_down(second_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [0.0, 202.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + // ] + // ); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, first_context_id); + // assert_eq!(grid.current_index(), 0); + // grid.split_right(third_context); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // assert_eq!(grid.current_index(), 2); + + // let contexts = grid.contexts(); + + // let scaled_padding = PADDING * contexts[0].val.dimension.dimension.scale; + + // // Check their respective width + // assert_eq!( + // contexts[0].val.dimension.width, + // (width / 2.) - scaled_padding + // ); + // assert_eq!(contexts[1].val.dimension.width, width); + // assert_eq!(contexts[2].val.dimension.width, width / 2.); + + // // Check their respective height + // let top_height = (height / 2.) - scaled_padding; + // assert_eq!(contexts[0].val.dimension.height, top_height); + // assert_eq!(contexts[1].val.dimension.height, height / 2.); + // assert_eq!(contexts[2].val.dimension.height, top_height); + + // // [RichText(RichText { id: 0, position: [0.0, 0.0] }), + // // Rect(Rect { position: [298.0, 0.0], color: [0.0, 0.0, 1.0, 0.0], size: [1.0, 396.0] }), + // // RichText(RichText { id: 2, position: [302.0, 0.0] }), + // // Rect(Rect { position: [0.0, 198.0], color: [0.0, 0.0, 1.0, 0.0], size: [596.0, 1.0] }), + // // RichText(RichText { id: 1, position: [0.0, 202.0] })] + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [298.0, 1.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [0.0, 202.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [298.0, 0.0], [1.0, 198.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [302.0, 0.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [302.0, 198.0], [300.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [602.0, 0.0], [1.0, 198.0]), + // ] + // ); + // } + + // #[test] + // fn test_remove_right_with_margin() { + // let margin = Delta { + // x: 20., + // top_y: 30., + // bottom_y: 40., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // })] + // ); + // grid.split_right(second_context); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + + // let first_expected_dimension = (286., 0.); + // let second_expected_dimension = (131., 0.); + // let third_expected_dimension = (135., 10.); + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); + // assert_eq!( + // contexts[0].val.dimension.margin.x, + // first_expected_dimension.1 + // ); + // assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); + // assert_eq!( + // contexts[1].val.dimension.margin.x, + // second_expected_dimension.1 + // ); + // assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); + // assert_eq!( + // contexts[2].val.dimension.margin.x, + // third_expected_dimension.1 + // ); + + // grid.select_prev_split(); + // grid.split_right(fourth_context); + + // // If the split right happens in not the last + // // then should not update margin to half of x + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 51.5); + // assert_eq!(contexts[1].val.dimension.margin.x, 0.); + // assert_eq!(contexts[3].val.dimension.width, 55.5); + // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + + // // 2 is the last one + // assert_eq!(contexts[2].val.dimension.width, 135.0); + // assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.], [143.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [167.0, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.], [25.75, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: fourth_context_id, + // position: [196.75, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.], [27.75, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [228.5, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.], [67.5, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), + // ] + // ); + + // grid.remove_current(); + + // // If the split right happens in not the last + // // then should not update margin to half of x + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); + // assert_eq!( + // contexts[0].val.dimension.margin.x, + // first_expected_dimension.1 + // ); + // assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); + // assert_eq!( + // contexts[1].val.dimension.margin.x, + // second_expected_dimension.1 + // ); + // assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); + // assert_eq!( + // contexts[2].val.dimension.margin.x, + // third_expected_dimension.1 + // ); + + // assert_eq!(grid.current_index(), 1); + // grid.select_next_split(); + // assert_eq!(grid.current_index(), 2); + + // // Margin x should move to last + // grid.remove_current(); + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 290.); + // assert_eq!(contexts[1].val.dimension.margin.x, 10.); + // } + + // #[test] + // fn test_split_down() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 1200.0, + // 800.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 85); + // assert_eq!(context_dimension.lines, 100); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + // grid.split_down(second_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [0.0, 202.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + // ] + // ); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_down(third_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [0.0, 202.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 300.0], [600.0, 1.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [0.0, 304.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 404.0], [600.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 304.0], [1.0, 100.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 98.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + // ] + // ); + // } + + // #[test] + // fn test_resize() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (third_context, _third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_right(second_context); + // grid.split_down(third_context); + + // // assert_eq!( + // // grid.objects(), + // // vec![ + // // Object::RichText(RichText { + // // id: first_context_id, + // // position: [0.0, 0.0], + // // }), + // // Object::Rect(Rect { + // // position: [147.0, 0.0], + // // color: [0.0, 0.0, 0.0, 0.0], + // // size: [1.0, 300.0] + // // }), + // // Object::RichText(RichText { + // // id: second_context_id, + // // position: [149.0, 0.0] + // // }), + // // Object::Rect(Rect { + // // position: [149.0, 147.0], + // // color: [0.0, 0.0, 0.0, 0.0], + // // size: [294.0, 1.0] + // // }), + // // Object::RichText(RichText { + // // id: third_context_id, + // // position: [149.0, 149.0] + // // }), + // // ] + // // ); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // grid.resize(1200.0, 600.0); + + // // TODO: Finish test + // } + + // #[test] + // fn test_remove_right_without_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + // assert_eq!(grid.current().dimension.width, 600.); + + // grid.split_right(second_context); + + // let new_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.width, new_expected_width); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // let old_expected_width = (600. / 2.) - scaled_padding; + // assert_eq!(grid.current().dimension.width, old_expected_width); + // assert_eq!(grid.current_index(), 0); + + // grid.select_next_split(); + // assert_eq!(grid.current_index(), 1); + + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 0); + // // Whenever return to one should drop padding + // assert_eq!(grid.current().dimension.width, 600.); + // } + + // #[test] + // fn test_remove_right_with_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_right(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // let old_context_expected_width = (600. / 2.) - scaled_padding; + // assert_eq!(grid.current().dimension.width, old_context_expected_width); + // assert_eq!(grid.current_index(), 0); + + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].right, Some(1)); + // assert_eq!(grid.contexts()[current_index].down, None); + + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 0); + // // Whenever return to one should drop padding + // let expected_width = 600.; + // assert_eq!(grid.current().dimension.width, expected_width); + + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].right, None); + // assert_eq!(grid.contexts()[current_index].down, None); + // } + + // #[test] + // fn test_remove_right_with_down_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_right(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current_index(), 1); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_down(third_context); + // assert_eq!(grid.current_index(), 2); + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current().dimension.height, 300.); + + // // Move back + // grid.select_prev_split(); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current().dimension.height, 296.); + + // // Remove the current should actually make right being down + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current().dimension.height, 600.); + // } + + // #[test] + // fn test_remove_down_without_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + // assert_eq!(grid.current().dimension.width, 600.); + + // grid.split_down(second_context); + + // let new_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_expected_width); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // let old_expected_width = (600. / 2.) - scaled_padding; + // assert_eq!(grid.current().dimension.height, old_expected_width); + // assert_eq!(grid.current_index(), 0); + + // grid.select_next_split(); + // assert_eq!(grid.current_index(), 1); + + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 0); + // // Whenever return to one should drop padding + // assert_eq!(grid.current().dimension.height, 600.); + // } + + // #[test] + // fn test_remove_down_with_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_down(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_height = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // let old_context_expected_height = (600. / 2.) - scaled_padding; + // assert_eq!(grid.current().dimension.height, old_context_expected_height); + // assert_eq!(grid.current_index(), 0); + + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].down, Some(1)); + // assert_eq!(grid.contexts()[current_index].right, None); + + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 0); + // // Whenever return to one should drop padding + // let expected_height = 600.; + // assert_eq!(grid.current().dimension.height, expected_height); + + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].down, None); + // assert_eq!(grid.contexts()[current_index].right, None); + // } + + // #[test] + // fn test_remove_down_with_right_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_down(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_height = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current_index(), 1); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + // assert_eq!(grid.current_index(), 2); + // assert_eq!(grid.current().dimension.width, new_context_expected_height); + // assert_eq!(grid.current().dimension.height, 300.); + + // // Move back + // grid.select_prev_split(); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current().dimension.width, 296.); + + // // Remove the current should actually make down being down + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current().dimension.width, 600.); + // } + + // #[test] + // fn test_remove_context_with_parent_but_down_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (third_context, third_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 4; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fifth_context, fifth_context_id) = { + // let rich_text_id = 5; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (sixth_context, sixth_context_id) = { + // let rich_text_id = 6; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // // The test is to validate the removal of a context with parenting however + // // should move to up the down items + // // + // // Test setup + // // + // // |1.-----|.3-----|4.-----| + // // |2.-----|.5-|6.-|-------| + + // grid.split_down(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_height = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, first_context_id); + + // grid.split_right(third_context); + // assert_eq!(grid.current().rich_text_id, third_context_id); + + // grid.split_right(fourth_context); + // assert_eq!(grid.current().rich_text_id, fourth_context_id); + + // let current_index = grid.current_index(); + // assert_eq!(current_index, 3); + // assert_eq!(grid.contexts()[current_index].down, None); + + // // So far we have: + // // + // // |1.-----|.3-----|4.-----| + // // |2.-----|-------|-------| + + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // let current_index = grid.current_index(); + // assert_eq!(current_index, 2); + // assert_eq!(grid.contexts()[current_index].down, None); + + // grid.split_down(fifth_context); + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + + // grid.split_right(sixth_context); + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + + // assert_eq!(grid.current().rich_text_id, third_context_id); + + // let current_index = grid.current_index(); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // fourth_context_id + // ); + // let current_index = grid.current_index(); + // let down = grid.contexts()[current_index].down; + // assert_eq!( + // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + // fifth_context_id + // ); + // // Setup complete, now we have 3 as active as well + // // + // // |1.-----|.3-----|4.-----| + // // |2.-----|.5-|6.-|-------| + // // + // // If we remove 3 then should be + // // + // // |1.-----|.5-|6.-|4.-----| + // // |2.-----|---|---|-------| + + // grid.remove_current(); + + // // Check if current is 5 and next is 6 + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + // let current_index = grid.current_index(); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // sixth_context_id + // ); + + // // Let's go back to 1 to check if leads to 5 + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + + // assert_eq!(grid.current().rich_text_id, first_context_id); + // let current_index = grid.current_index(); + // assert_eq!(current_index, 0); + // let right = grid.contexts()[current_index].right; + // assert_eq!(right, Some(3)); + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // fifth_context_id + // ); + + // // Let's go to 6 to check if leads to 4 + // // + // // |1.-----|.5-|6.-|4.-----| + // // |2.-----|---|---|-------| + + // grid.select_next_split(); + // grid.select_next_split(); + // grid.select_next_split(); + // grid.select_next_split(); + + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + // let current_index = grid.current_index(); + // let right = grid.contexts()[current_index].right; + // assert_eq!(right, Some(2)); + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // fourth_context_id + // ); + // } + + // #[test] + // fn test_remove_context_without_parents_but_with_right_and_down_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (third_context, third_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 4; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_right(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, second_context_id); + + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, first_context_id); + + // grid.split_down(third_context); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // assert_eq!(grid.current().dimension.width, 296.); + // assert_eq!(grid.current().dimension.height, 300.); + + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // grid.split_down(fourth_context); + + // assert_eq!(grid.current_index(), 3); + // assert_eq!(grid.current().rich_text_id, fourth_context_id); + + // grid.select_next_split(); + // assert_eq!(grid.current_index(), 0); + // assert_eq!(grid.current().rich_text_id, first_context_id); + + // // Active is 1 + // // |1.----|.2----| + // // |3.----|.4----| + + // // Remove the current should actually make right being down + // grid.remove_current(); + // let current_index = grid.current_index(); + // // Move third context to first position + // assert_eq!(current_index, 0); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // let right = grid.contexts()[current_index].right; + // let right_context = grid.contexts()[right.unwrap_or_default()].val.rich_text_id; + // assert_eq!(right_context, second_context_id); + + // // Result: + // // |3.----|.2----| + // // |------|.4----| + + // // Now let's create a more complex case + // // |3.---------|.2---------| + // // |5.-|6.-|7.-|.4---------| + + // let (fifth_context, fifth_context_id) = { + // let rich_text_id = 5; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (sixth_context, sixth_context_id) = { + // let rich_text_id = 6; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (seventh_context, seventh_context_id) = { + // let rich_text_id = 7; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_down(fifth_context); + // grid.split_right(sixth_context); + // grid.split_right(seventh_context); + + // assert_eq!(grid.current_index(), 5); + // assert_eq!(grid.current().rich_text_id, seventh_context_id); + + // // Current: + // // |3.---------|.2---------| + // // |5.-|6.-|7.-|.4---------| + // // + // // Now if we move back to 3. and remove it: + // // Should move 5, 6 and 7 to top. + // // + // // |5.-|6.-|7.-|.2---------| + // // |---|---|---|.4---------| + // grid.select_next_split(); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // let current_index = grid.current_index(); + // let down = grid.contexts()[current_index].down; + // assert_eq!( + // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + // fifth_context_id + // ); + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + + // let current_index = grid.current_index(); + // let right = grid.contexts()[current_index].right.unwrap_or_default(); + // let right_context = &grid.contexts()[right]; + // assert_eq!(right_context.val.rich_text_id, sixth_context_id); + + // // Current: + // // |5.-|6.-|7.-|.2---------| + // // |---|---|---|.4---------| + + // // Ok, let's test the reverse to right operations + // // First remove 5 and 6 + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].down, None); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // seventh_context_id + // ); + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, seventh_context_id); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // second_context_id + // ); + + // // Current: + // // |7.---------|.2---------| + // // |-----------|.4---------| + + // // Now let's add many 5 and 6 as down items on 7th + // // + // // Should be: + // // |7.---------|.2---------| + // // |5.---------|.4---------| + // // |6.---------|-----------| + + // let (fifth_context, fifth_context_id) = { + // let rich_text_id = 5; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (sixth_context, sixth_context_id) = { + // let rich_text_id = 6; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_down(fifth_context); + // grid.split_down(sixth_context); + + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, seventh_context_id); + + // // Next step remove 7 + // // + // // Should be: + // // |5.---------|.2---------| + // // |6.---------|.4---------| + // // |-----------|-----------| + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + // let right = grid.contexts()[current_index].right; + // let down = grid.contexts()[current_index].down; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // second_context_id + // ); + // assert_eq!( + // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + // sixth_context_id + // ); + + // // Next step remove 5 + // // + // // Should be: + // // |6.---------|.2---------| + // // |-----------|.4---------| + // // |-----------|-----------| + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // second_context_id + // ); + // assert_eq!(grid.contexts()[current_index].down, None); + // } + + // #[test] + // fn test_select_current_based_on_mouse() { + // let mut mouse = Mouse::default(); + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.select_current_based_on_mouse(&mouse); + // // On first should always return first item + // assert_eq!(grid.current_index(), 0); + + // grid.split_down(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_height = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current_index(), 1); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + // assert_eq!(grid.current_index(), 2); + // assert_eq!(grid.current().dimension.width, new_context_expected_height); + // assert_eq!(grid.current().dimension.height, 300.); + + // grid.select_current_based_on_mouse(&mouse); + // assert_eq!(grid.current_index(), 0); + // assert_eq!(grid.current().rich_text_id, 0); + + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // mouse.y = (new_context_expected_height + scaled_padding) as usize; + // grid.select_current_based_on_mouse(&mouse); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, second_context_id); + + // mouse.x = 304; + // grid.select_current_based_on_mouse(&mouse); + + // assert_eq!(grid.current_index(), 2); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // } } diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index f1e54e9630..8541630300 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -1059,189 +1059,189 @@ pub mod test { use super::*; use crate::event::VoidListener; - #[test] - fn test_capacity() { - let window_id: WindowId = WindowId::from(0); - - let context_manager = - ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - assert_eq!(context_manager.capacity, 5); - - let mut context_manager = - ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - context_manager.increase_capacity(3); - assert_eq!(context_manager.capacity, 8); - } - - #[test] - fn test_add_context() { - let window_id: WindowId = WindowId::from(0); - - let mut context_manager = - ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - assert_eq!(context_manager.capacity, 5); - assert_eq!(context_manager.current_index, 0); - - let should_redirect = false; - context_manager.add_context(should_redirect, 0); - assert_eq!(context_manager.capacity, 5); - assert_eq!(context_manager.current_index, 0); - - let should_redirect = true; - context_manager.add_context(should_redirect, 0); - assert_eq!(context_manager.capacity, 5); - assert_eq!(context_manager.current_index, 2); - } - - #[test] - fn test_add_context_start_with_capacity_limit() { - let window_id: WindowId = WindowId::from(0); - - let mut context_manager = - ContextManager::start_with_capacity(3, VoidListener {}, window_id).unwrap(); - assert_eq!(context_manager.capacity, 3); - assert_eq!(context_manager.current_index, 0); - let should_redirect = false; - context_manager.add_context(should_redirect, 0); - assert_eq!(context_manager.len(), 2); - context_manager.add_context(should_redirect, 0); - assert_eq!(context_manager.len(), 3); - - for _ in 0..20 { - context_manager.add_context(should_redirect, 0); - } - - assert_eq!(context_manager.len(), 3); - assert_eq!(context_manager.capacity, 3); - } - - #[test] - fn test_set_current() { - let window_id: WindowId = WindowId::from(0); - - let mut context_manager = - ContextManager::start_with_capacity(8, VoidListener {}, window_id).unwrap(); - let should_redirect = true; - - context_manager.add_context(should_redirect, 0); - assert_eq!(context_manager.current_index, 1); - context_manager.set_current(0); - assert_eq!(context_manager.current_index, 0); - assert_eq!(context_manager.len(), 2); - assert_eq!(context_manager.capacity, 8); - - let should_redirect = false; - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - context_manager.set_current(3); - assert_eq!(context_manager.current_index, 3); - - context_manager.set_current(8); - assert_eq!(context_manager.current_index, 3); - } - - #[test] - fn test_close_context() { - let window_id: WindowId = WindowId::from(0); - - let mut context_manager = - ContextManager::start_with_capacity(3, VoidListener {}, window_id).unwrap(); - let should_redirect = false; - - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - assert_eq!(context_manager.len(), 3); - - assert_eq!(context_manager.current_index, 0); - context_manager.set_current(2); - assert_eq!(context_manager.current_index, 2); - context_manager.set_current(0); - - context_manager.close_current_context(); - context_manager.set_current(2); - assert_eq!(context_manager.current_index, 0); - assert_eq!(context_manager.len(), 2); - } - - #[test] - fn test_close_context_upcoming_ids() { - let window_id: WindowId = WindowId::from(0); - - let mut context_manager = - ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - let should_redirect = false; - - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - - context_manager.close_current_context(); - context_manager.close_current_context(); - context_manager.close_current_context(); - context_manager.close_current_context(); - - assert_eq!(context_manager.len(), 1); - assert_eq!(context_manager.current_index, 0); - - context_manager.add_context(should_redirect, 0); - - assert_eq!(context_manager.len(), 2); - context_manager.set_current(1); - assert_eq!(context_manager.current_index, 1); - context_manager.close_current_context(); - assert_eq!(context_manager.len(), 1); - assert_eq!(context_manager.current_index, 0); - } - - #[test] - fn test_close_last_context() { - let window_id: WindowId = WindowId::from(0); - - let mut context_manager = - ContextManager::start_with_capacity(2, VoidListener {}, window_id).unwrap(); - let should_redirect = false; - - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - assert_eq!(context_manager.len(), 2); - assert_eq!(context_manager.current_index, 0); - - context_manager.close_current_context(); - assert_eq!(context_manager.len(), 1); - - // Last context should not be closed - context_manager.close_current_context(); - assert_eq!(context_manager.len(), 1); - } - - #[test] - fn test_switch_to_next() { - let window_id: WindowId = WindowId::from(0); - - let mut context_manager = - ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - let should_redirect = false; - - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - context_manager.add_context(should_redirect, 0); - assert_eq!(context_manager.len(), 5); - assert_eq!(context_manager.current_index, 0); - - context_manager.switch_to_next(); - assert_eq!(context_manager.current_index, 1); - context_manager.switch_to_next(); - assert_eq!(context_manager.current_index, 2); - context_manager.switch_to_next(); - assert_eq!(context_manager.current_index, 3); - context_manager.switch_to_next(); - assert_eq!(context_manager.current_index, 4); - context_manager.switch_to_next(); - assert_eq!(context_manager.current_index, 0); - context_manager.switch_to_next(); - assert_eq!(context_manager.current_index, 1); - } + // #[test] + // fn test_capacity() { + // let window_id: WindowId = WindowId::from(0); + + // let context_manager = + // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + // assert_eq!(context_manager.capacity, 5); + + // let mut context_manager = + // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + // context_manager.increase_capacity(3); + // assert_eq!(context_manager.capacity, 8); + // } + + // #[test] + // fn test_add_context() { + // let window_id: WindowId = WindowId::from(0); + + // let mut context_manager = + // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + // assert_eq!(context_manager.capacity, 5); + // assert_eq!(context_manager.current_index, 0); + + // let should_redirect = false; + // context_manager.add_context(should_redirect, 0); + // assert_eq!(context_manager.capacity, 5); + // assert_eq!(context_manager.current_index, 0); + + // let should_redirect = true; + // context_manager.add_context(should_redirect, 0); + // assert_eq!(context_manager.capacity, 5); + // assert_eq!(context_manager.current_index, 2); + // } + + // #[test] + // fn test_add_context_start_with_capacity_limit() { + // let window_id: WindowId = WindowId::from(0); + + // let mut context_manager = + // ContextManager::start_with_capacity(3, VoidListener {}, window_id).unwrap(); + // assert_eq!(context_manager.capacity, 3); + // assert_eq!(context_manager.current_index, 0); + // let should_redirect = false; + // context_manager.add_context(should_redirect, 0); + // assert_eq!(context_manager.len(), 2); + // context_manager.add_context(should_redirect, 0); + // assert_eq!(context_manager.len(), 3); + + // for _ in 0..20 { + // context_manager.add_context(should_redirect, 0); + // } + + // assert_eq!(context_manager.len(), 3); + // assert_eq!(context_manager.capacity, 3); + // } + + // #[test] + // fn test_set_current() { + // let window_id: WindowId = WindowId::from(0); + + // let mut context_manager = + // ContextManager::start_with_capacity(8, VoidListener {}, window_id).unwrap(); + // let should_redirect = true; + + // context_manager.add_context(should_redirect, 0); + // assert_eq!(context_manager.current_index, 1); + // context_manager.set_current(0); + // assert_eq!(context_manager.current_index, 0); + // assert_eq!(context_manager.len(), 2); + // assert_eq!(context_manager.capacity, 8); + + // let should_redirect = false; + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + // context_manager.set_current(3); + // assert_eq!(context_manager.current_index, 3); + + // context_manager.set_current(8); + // assert_eq!(context_manager.current_index, 3); + // } + + // #[test] + // fn test_close_context() { + // let window_id: WindowId = WindowId::from(0); + + // let mut context_manager = + // ContextManager::start_with_capacity(3, VoidListener {}, window_id).unwrap(); + // let should_redirect = false; + + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + // assert_eq!(context_manager.len(), 3); + + // assert_eq!(context_manager.current_index, 0); + // context_manager.set_current(2); + // assert_eq!(context_manager.current_index, 2); + // context_manager.set_current(0); + + // context_manager.close_current_context(); + // context_manager.set_current(2); + // assert_eq!(context_manager.current_index, 0); + // assert_eq!(context_manager.len(), 2); + // } + + // #[test] + // fn test_close_context_upcoming_ids() { + // let window_id: WindowId = WindowId::from(0); + + // let mut context_manager = + // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + // let should_redirect = false; + + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + + // context_manager.close_current_context(); + // context_manager.close_current_context(); + // context_manager.close_current_context(); + // context_manager.close_current_context(); + + // assert_eq!(context_manager.len(), 1); + // assert_eq!(context_manager.current_index, 0); + + // context_manager.add_context(should_redirect, 0); + + // assert_eq!(context_manager.len(), 2); + // context_manager.set_current(1); + // assert_eq!(context_manager.current_index, 1); + // context_manager.close_current_context(); + // assert_eq!(context_manager.len(), 1); + // assert_eq!(context_manager.current_index, 0); + // } + + // #[test] + // fn test_close_last_context() { + // let window_id: WindowId = WindowId::from(0); + + // let mut context_manager = + // ContextManager::start_with_capacity(2, VoidListener {}, window_id).unwrap(); + // let should_redirect = false; + + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + // assert_eq!(context_manager.len(), 2); + // assert_eq!(context_manager.current_index, 0); + + // context_manager.close_current_context(); + // assert_eq!(context_manager.len(), 1); + + // // Last context should not be closed + // context_manager.close_current_context(); + // assert_eq!(context_manager.len(), 1); + // } + + // #[test] + // fn test_switch_to_next() { + // let window_id: WindowId = WindowId::from(0); + + // let mut context_manager = + // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + // let should_redirect = false; + + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + // context_manager.add_context(should_redirect, 0); + // assert_eq!(context_manager.len(), 5); + // assert_eq!(context_manager.current_index, 0); + + // context_manager.switch_to_next(); + // assert_eq!(context_manager.current_index, 1); + // context_manager.switch_to_next(); + // assert_eq!(context_manager.current_index, 2); + // context_manager.switch_to_next(); + // assert_eq!(context_manager.current_index, 3); + // context_manager.switch_to_next(); + // assert_eq!(context_manager.current_index, 4); + // context_manager.switch_to_next(); + // assert_eq!(context_manager.current_index, 0); + // context_manager.switch_to_next(); + // assert_eq!(context_manager.current_index, 1); + // } } From c12f1b54c2c26013565652131878c9f225534ec9 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Fri, 20 Dec 2024 21:53:44 -0300 Subject: [PATCH 03/20] pull back grid tests --- frontends/rioterm/src/context/grid.rs | 5228 ++++++++++++------------- 1 file changed, 2614 insertions(+), 2614 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index f9189bd42e..de49be4807 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -969,2618 +969,2618 @@ pub mod test { use pretty_assertions::assert_eq; use rio_window::window::WindowId; - // #[test] - // fn test_single_context_respecting_margin_and_no_quad_creation() { - // let margin = Delta { - // x: 10., - // top_y: 20., - // bottom_y: 20., - // }; - - // let context_dimension = ContextDimension::build( - // 1200.0, - // 800.0, - // SugarDimensions { - // scale: 2., - // width: 18., - // height: 9., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 66); - // assert_eq!(context_dimension.lines, 88); - // let rich_text_id = 1; - // let route_id = 0; - // let context = create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ); - // let context_width = context.dimension.width; - // let context_height = context.dimension.height; - // let context_margin = context.dimension.margin; - // let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); - // // The first context should fill completely w/h grid - // assert_eq!(grid.width, context_width); - // assert_eq!(grid.height, context_height); - - // // Context margin should empty - // assert_eq!(Delta::::default(), context_margin); - // assert_eq!(grid.margin, margin); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: rich_text_id, - // position: [10., 20.], - // })] - // ); - // } - - // #[test] - // fn test_split_right() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 1200.0, - // 800.0, - // SugarDimensions { - // scale: 1., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 85); - // assert_eq!(context_dimension.lines, 100); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - // grid.split_right(second_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [600., 0.0] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - // ] - // ); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [600.0, 0.0] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [900.0, 0.0] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - // ] - // ); - // } - - // #[test] - // fn test_split_right_with_margin() { - // let margin = Delta { - // x: 20., - // top_y: 30., - // bottom_y: 40., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // })] - // ); - // grid.split_right(second_context); - - // /* - // > before split: - // 20 (600/20) - // |------| - - // Available width should compute with margin - // so should be 600 - 20 = 580, then will be: - // 289 + 4 (PADDING) + 290 - - // > after split: - // 10 (289/0) (4) (290/10) - // |----------|----------| - - // Margin should be splitted between first columns - // items and last columns items - // */ - - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 290.); - // assert_eq!(contexts[1].val.dimension.margin.x, 10.); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [167.0, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [145.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [312.0, margin.top_y], [1.0, 300.0]), - // ] - // ); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [167.0, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [65.5, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [232.5, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [236.5, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [236.5, 330.0], [67.5, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [304.0, margin.top_y], [1.0, 300.0]), - // ] - // ); - - // // Last context should be updated with half of x - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 131.); - // assert_eq!(contexts[1].val.dimension.margin.x, 0.); - // assert_eq!(contexts[2].val.dimension.width, 135.); - // assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.select_prev_split(); - // grid.split_right(fourth_context); - - // // If the split right happens in not the last - // // then should not update margin to half of x - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 51.5); - // assert_eq!(contexts[1].val.dimension.margin.x, 0.); - // assert_eq!(contexts[3].val.dimension.width, 55.5); - // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - - // // 2 is the last one - // assert_eq!(contexts[2].val.dimension.width, 135.0); - // assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [167.0, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [25.75, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: fourth_context_id, - // position: [196.75, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.0], [27.75, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [228.5, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.0], [67.5, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), - // ] - // ); - // } - - // #[test] - // fn test_split_right_with_margin_inside_parent() { - // let margin = Delta { - // x: 20., - // top_y: 30., - // bottom_y: 40., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // })] - // ); - - // let (third_context, _third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, _fourth_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fifth_context, _fifth_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(second_context); - // grid.select_prev_split(); - // grid.split_down(third_context); - // grid.split_right(fourth_context); - // grid.split_right(fifth_context); - - // // If the split right happens in not the last - // // then should not update margin to half of x - - // assert_eq!(grid.current_index(), 4); - - // // |1.--------------|2.------------| - // // |3.----|4.--|5.--|--------------| - // let contexts = grid.contexts(); - // assert_eq!(contexts.len(), 5); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 290.); - // assert_eq!(contexts[1].val.dimension.margin.x, 10.); - // assert_eq!(contexts[2].val.dimension.width, 129.0); - // assert_eq!(contexts[2].val.dimension.margin.x, 0.); - // assert_eq!(contexts[3].val.dimension.width, 52.5); - // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - // assert_eq!(contexts[4].val.dimension.width, 56.5); - - // // Fifth context should not have any margin x - // // TODO: - // // assert_eq!(contexts[4].val.dimension.margin.x, 0.); - - // grid.remove_current(); - // assert_eq!(grid.current_index(), 3); - // let contexts = grid.contexts(); - // assert_eq!(contexts[1].val.dimension.margin.x, 10.); - // // Fourth context should not have any margin x - // // TODO: - // // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - // } - - // #[test] - // fn test_split_down_with_margin_inside_parent() { - // let margin = Delta { - // x: 20., - // top_y: 30., - // bottom_y: 40., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 1., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (third_context, third_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 4; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fifth_context, fifth_context_id) = { - // let rich_text_id = 5; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // })] - // ); - - // grid.split_down(second_context); - // grid.split_down(third_context); - // grid.split_right(fourth_context); - // grid.select_prev_split(); - // grid.select_prev_split(); - // let current_index = grid.current_index(); - // let contexts = grid.contexts(); - // assert_eq!(contexts[current_index].val.rich_text_id, second_context_id); - // grid.split_right(fifth_context); - - // // If the split right happens in not the last - // // then should not update margin to half of x - - // assert_eq!(grid.current_index(), 4); - - // // |1.--------------| - // // |2.------|5.-----| - // // |3.------|4.-----| - // let contexts = grid.contexts(); - // assert_eq!(contexts.len(), 5); - - // assert_eq!(contexts[0].val.rich_text_id, first_context_id); - // assert_eq!(contexts[0].val.dimension.height, 298.); - // assert_eq!(contexts[0].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[0].val.dimension.margin.bottom_y, 0.); - // let first_down = contexts[0].down; - // assert_eq!(first_down, Some(1)); - // assert_eq!( - // contexts[first_down.unwrap_or_default()].val.rich_text_id, - // second_context_id - // ); - - // assert_eq!(contexts[1].val.rich_text_id, second_context_id); - // assert_eq!(contexts[1].val.dimension.height, 148.); - // assert_eq!(contexts[1].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[1].val.dimension.margin.bottom_y, 0.); - - // assert_eq!(contexts[4].val.rich_text_id, fifth_context_id); - // assert_eq!(contexts[4].val.dimension.height, 148.0); - // assert_eq!(contexts[4].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[4].val.dimension.margin.bottom_y, 0.); - - // assert_eq!(contexts[2].val.rich_text_id, third_context_id); - // assert_eq!(contexts[2].val.dimension.height, 150.0); - // assert_eq!(contexts[2].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[2].val.dimension.margin.bottom_y, 40.); - - // assert_eq!(contexts[3].val.rich_text_id, fourth_context_id); - // assert_eq!(contexts[3].val.dimension.height, 150.0); - // assert_eq!(contexts[3].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[3].val.dimension.margin.bottom_y, 40.); - - // // Fifth context should not have any margin x - // // TODO: Removal - // // grid.remove_current(); - // } - - // #[test] - // // https://github.com/raphamorim/rio/issues/760 - // fn test_split_issue_760() { - // let width = 1200.; - // let height = 800.; - - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // width, - // height, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 85); - // assert_eq!(context_dimension.lines, 100); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - // grid.split_down(second_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [0.0, 202.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - // ] - // ); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, first_context_id); - // assert_eq!(grid.current_index(), 0); - // grid.split_right(third_context); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // assert_eq!(grid.current_index(), 2); - - // let contexts = grid.contexts(); - - // let scaled_padding = PADDING * contexts[0].val.dimension.dimension.scale; - - // // Check their respective width - // assert_eq!( - // contexts[0].val.dimension.width, - // (width / 2.) - scaled_padding - // ); - // assert_eq!(contexts[1].val.dimension.width, width); - // assert_eq!(contexts[2].val.dimension.width, width / 2.); - - // // Check their respective height - // let top_height = (height / 2.) - scaled_padding; - // assert_eq!(contexts[0].val.dimension.height, top_height); - // assert_eq!(contexts[1].val.dimension.height, height / 2.); - // assert_eq!(contexts[2].val.dimension.height, top_height); - - // // [RichText(RichText { id: 0, position: [0.0, 0.0] }), - // // Rect(Rect { position: [298.0, 0.0], color: [0.0, 0.0, 1.0, 0.0], size: [1.0, 396.0] }), - // // RichText(RichText { id: 2, position: [302.0, 0.0] }), - // // Rect(Rect { position: [0.0, 198.0], color: [0.0, 0.0, 1.0, 0.0], size: [596.0, 1.0] }), - // // RichText(RichText { id: 1, position: [0.0, 202.0] })] - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [298.0, 1.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [0.0, 202.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [298.0, 0.0], [1.0, 198.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [302.0, 0.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [302.0, 198.0], [300.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [602.0, 0.0], [1.0, 198.0]), - // ] - // ); - // } - - // #[test] - // fn test_remove_right_with_margin() { - // let margin = Delta { - // x: 20., - // top_y: 30., - // bottom_y: 40., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // })] - // ); - // grid.split_right(second_context); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - - // let first_expected_dimension = (286., 0.); - // let second_expected_dimension = (131., 0.); - // let third_expected_dimension = (135., 10.); - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); - // assert_eq!( - // contexts[0].val.dimension.margin.x, - // first_expected_dimension.1 - // ); - // assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); - // assert_eq!( - // contexts[1].val.dimension.margin.x, - // second_expected_dimension.1 - // ); - // assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); - // assert_eq!( - // contexts[2].val.dimension.margin.x, - // third_expected_dimension.1 - // ); - - // grid.select_prev_split(); - // grid.split_right(fourth_context); - - // // If the split right happens in not the last - // // then should not update margin to half of x - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 51.5); - // assert_eq!(contexts[1].val.dimension.margin.x, 0.); - // assert_eq!(contexts[3].val.dimension.width, 55.5); - // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - - // // 2 is the last one - // assert_eq!(contexts[2].val.dimension.width, 135.0); - // assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.], [143.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [167.0, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.], [25.75, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: fourth_context_id, - // position: [196.75, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.], [27.75, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [228.5, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.], [67.5, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), - // ] - // ); - - // grid.remove_current(); - - // // If the split right happens in not the last - // // then should not update margin to half of x - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); - // assert_eq!( - // contexts[0].val.dimension.margin.x, - // first_expected_dimension.1 - // ); - // assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); - // assert_eq!( - // contexts[1].val.dimension.margin.x, - // second_expected_dimension.1 - // ); - // assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); - // assert_eq!( - // contexts[2].val.dimension.margin.x, - // third_expected_dimension.1 - // ); - - // assert_eq!(grid.current_index(), 1); - // grid.select_next_split(); - // assert_eq!(grid.current_index(), 2); - - // // Margin x should move to last - // grid.remove_current(); - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 290.); - // assert_eq!(contexts[1].val.dimension.margin.x, 10.); - // } - - // #[test] - // fn test_split_down() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 1200.0, - // 800.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 85); - // assert_eq!(context_dimension.lines, 100); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - // grid.split_down(second_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [0.0, 202.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - // ] - // ); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_down(third_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [0.0, 202.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 300.0], [600.0, 1.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [0.0, 304.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 404.0], [600.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 304.0], [1.0, 100.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 98.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - // ] - // ); - // } - - // #[test] - // fn test_resize() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (third_context, _third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_right(second_context); - // grid.split_down(third_context); - - // // assert_eq!( - // // grid.objects(), - // // vec![ - // // Object::RichText(RichText { - // // id: first_context_id, - // // position: [0.0, 0.0], - // // }), - // // Object::Rect(Rect { - // // position: [147.0, 0.0], - // // color: [0.0, 0.0, 0.0, 0.0], - // // size: [1.0, 300.0] - // // }), - // // Object::RichText(RichText { - // // id: second_context_id, - // // position: [149.0, 0.0] - // // }), - // // Object::Rect(Rect { - // // position: [149.0, 147.0], - // // color: [0.0, 0.0, 0.0, 0.0], - // // size: [294.0, 1.0] - // // }), - // // Object::RichText(RichText { - // // id: third_context_id, - // // position: [149.0, 149.0] - // // }), - // // ] - // // ); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // grid.resize(1200.0, 600.0); - - // // TODO: Finish test - // } - - // #[test] - // fn test_remove_right_without_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - // assert_eq!(grid.current().dimension.width, 600.); - - // grid.split_right(second_context); - - // let new_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.width, new_expected_width); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // let old_expected_width = (600. / 2.) - scaled_padding; - // assert_eq!(grid.current().dimension.width, old_expected_width); - // assert_eq!(grid.current_index(), 0); - - // grid.select_next_split(); - // assert_eq!(grid.current_index(), 1); - - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 0); - // // Whenever return to one should drop padding - // assert_eq!(grid.current().dimension.width, 600.); - // } - - // #[test] - // fn test_remove_right_with_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_right(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // let old_context_expected_width = (600. / 2.) - scaled_padding; - // assert_eq!(grid.current().dimension.width, old_context_expected_width); - // assert_eq!(grid.current_index(), 0); - - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].right, Some(1)); - // assert_eq!(grid.contexts()[current_index].down, None); - - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 0); - // // Whenever return to one should drop padding - // let expected_width = 600.; - // assert_eq!(grid.current().dimension.width, expected_width); - - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].right, None); - // assert_eq!(grid.contexts()[current_index].down, None); - // } - - // #[test] - // fn test_remove_right_with_down_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_right(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current_index(), 1); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_down(third_context); - // assert_eq!(grid.current_index(), 2); - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current().dimension.height, 300.); - - // // Move back - // grid.select_prev_split(); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current().dimension.height, 296.); - - // // Remove the current should actually make right being down - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current().dimension.height, 600.); - // } - - // #[test] - // fn test_remove_down_without_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - // assert_eq!(grid.current().dimension.width, 600.); - - // grid.split_down(second_context); - - // let new_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_expected_width); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // let old_expected_width = (600. / 2.) - scaled_padding; - // assert_eq!(grid.current().dimension.height, old_expected_width); - // assert_eq!(grid.current_index(), 0); - - // grid.select_next_split(); - // assert_eq!(grid.current_index(), 1); - - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 0); - // // Whenever return to one should drop padding - // assert_eq!(grid.current().dimension.height, 600.); - // } - - // #[test] - // fn test_remove_down_with_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_down(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_height = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // let old_context_expected_height = (600. / 2.) - scaled_padding; - // assert_eq!(grid.current().dimension.height, old_context_expected_height); - // assert_eq!(grid.current_index(), 0); - - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].down, Some(1)); - // assert_eq!(grid.contexts()[current_index].right, None); - - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 0); - // // Whenever return to one should drop padding - // let expected_height = 600.; - // assert_eq!(grid.current().dimension.height, expected_height); - - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].down, None); - // assert_eq!(grid.contexts()[current_index].right, None); - // } - - // #[test] - // fn test_remove_down_with_right_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_down(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_height = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current_index(), 1); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - // assert_eq!(grid.current_index(), 2); - // assert_eq!(grid.current().dimension.width, new_context_expected_height); - // assert_eq!(grid.current().dimension.height, 300.); - - // // Move back - // grid.select_prev_split(); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current().dimension.width, 296.); - - // // Remove the current should actually make down being down - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current().dimension.width, 600.); - // } - - // #[test] - // fn test_remove_context_with_parent_but_down_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (third_context, third_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 4; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fifth_context, fifth_context_id) = { - // let rich_text_id = 5; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (sixth_context, sixth_context_id) = { - // let rich_text_id = 6; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // // The test is to validate the removal of a context with parenting however - // // should move to up the down items - // // - // // Test setup - // // - // // |1.-----|.3-----|4.-----| - // // |2.-----|.5-|6.-|-------| - - // grid.split_down(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_height = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, first_context_id); - - // grid.split_right(third_context); - // assert_eq!(grid.current().rich_text_id, third_context_id); - - // grid.split_right(fourth_context); - // assert_eq!(grid.current().rich_text_id, fourth_context_id); - - // let current_index = grid.current_index(); - // assert_eq!(current_index, 3); - // assert_eq!(grid.contexts()[current_index].down, None); - - // // So far we have: - // // - // // |1.-----|.3-----|4.-----| - // // |2.-----|-------|-------| - - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // let current_index = grid.current_index(); - // assert_eq!(current_index, 2); - // assert_eq!(grid.contexts()[current_index].down, None); - - // grid.split_down(fifth_context); - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - - // grid.split_right(sixth_context); - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - - // assert_eq!(grid.current().rich_text_id, third_context_id); - - // let current_index = grid.current_index(); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // fourth_context_id - // ); - // let current_index = grid.current_index(); - // let down = grid.contexts()[current_index].down; - // assert_eq!( - // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - // fifth_context_id - // ); - // // Setup complete, now we have 3 as active as well - // // - // // |1.-----|.3-----|4.-----| - // // |2.-----|.5-|6.-|-------| - // // - // // If we remove 3 then should be - // // - // // |1.-----|.5-|6.-|4.-----| - // // |2.-----|---|---|-------| - - // grid.remove_current(); - - // // Check if current is 5 and next is 6 - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - // let current_index = grid.current_index(); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // sixth_context_id - // ); - - // // Let's go back to 1 to check if leads to 5 - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - - // assert_eq!(grid.current().rich_text_id, first_context_id); - // let current_index = grid.current_index(); - // assert_eq!(current_index, 0); - // let right = grid.contexts()[current_index].right; - // assert_eq!(right, Some(3)); - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // fifth_context_id - // ); - - // // Let's go to 6 to check if leads to 4 - // // - // // |1.-----|.5-|6.-|4.-----| - // // |2.-----|---|---|-------| - - // grid.select_next_split(); - // grid.select_next_split(); - // grid.select_next_split(); - // grid.select_next_split(); - - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - // let current_index = grid.current_index(); - // let right = grid.contexts()[current_index].right; - // assert_eq!(right, Some(2)); - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // fourth_context_id - // ); - // } - - // #[test] - // fn test_remove_context_without_parents_but_with_right_and_down_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (third_context, third_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 4; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_right(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, second_context_id); - - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, first_context_id); - - // grid.split_down(third_context); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // assert_eq!(grid.current().dimension.width, 296.); - // assert_eq!(grid.current().dimension.height, 300.); - - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // grid.split_down(fourth_context); - - // assert_eq!(grid.current_index(), 3); - // assert_eq!(grid.current().rich_text_id, fourth_context_id); - - // grid.select_next_split(); - // assert_eq!(grid.current_index(), 0); - // assert_eq!(grid.current().rich_text_id, first_context_id); - - // // Active is 1 - // // |1.----|.2----| - // // |3.----|.4----| - - // // Remove the current should actually make right being down - // grid.remove_current(); - // let current_index = grid.current_index(); - // // Move third context to first position - // assert_eq!(current_index, 0); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // let right = grid.contexts()[current_index].right; - // let right_context = grid.contexts()[right.unwrap_or_default()].val.rich_text_id; - // assert_eq!(right_context, second_context_id); - - // // Result: - // // |3.----|.2----| - // // |------|.4----| - - // // Now let's create a more complex case - // // |3.---------|.2---------| - // // |5.-|6.-|7.-|.4---------| - - // let (fifth_context, fifth_context_id) = { - // let rich_text_id = 5; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (sixth_context, sixth_context_id) = { - // let rich_text_id = 6; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (seventh_context, seventh_context_id) = { - // let rich_text_id = 7; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_down(fifth_context); - // grid.split_right(sixth_context); - // grid.split_right(seventh_context); - - // assert_eq!(grid.current_index(), 5); - // assert_eq!(grid.current().rich_text_id, seventh_context_id); - - // // Current: - // // |3.---------|.2---------| - // // |5.-|6.-|7.-|.4---------| - // // - // // Now if we move back to 3. and remove it: - // // Should move 5, 6 and 7 to top. - // // - // // |5.-|6.-|7.-|.2---------| - // // |---|---|---|.4---------| - // grid.select_next_split(); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // let current_index = grid.current_index(); - // let down = grid.contexts()[current_index].down; - // assert_eq!( - // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - // fifth_context_id - // ); - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - - // let current_index = grid.current_index(); - // let right = grid.contexts()[current_index].right.unwrap_or_default(); - // let right_context = &grid.contexts()[right]; - // assert_eq!(right_context.val.rich_text_id, sixth_context_id); - - // // Current: - // // |5.-|6.-|7.-|.2---------| - // // |---|---|---|.4---------| - - // // Ok, let's test the reverse to right operations - // // First remove 5 and 6 - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].down, None); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // seventh_context_id - // ); - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, seventh_context_id); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // second_context_id - // ); - - // // Current: - // // |7.---------|.2---------| - // // |-----------|.4---------| - - // // Now let's add many 5 and 6 as down items on 7th - // // - // // Should be: - // // |7.---------|.2---------| - // // |5.---------|.4---------| - // // |6.---------|-----------| - - // let (fifth_context, fifth_context_id) = { - // let rich_text_id = 5; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (sixth_context, sixth_context_id) = { - // let rich_text_id = 6; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_down(fifth_context); - // grid.split_down(sixth_context); - - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, seventh_context_id); - - // // Next step remove 7 - // // - // // Should be: - // // |5.---------|.2---------| - // // |6.---------|.4---------| - // // |-----------|-----------| - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - // let right = grid.contexts()[current_index].right; - // let down = grid.contexts()[current_index].down; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // second_context_id - // ); - // assert_eq!( - // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - // sixth_context_id - // ); - - // // Next step remove 5 - // // - // // Should be: - // // |6.---------|.2---------| - // // |-----------|.4---------| - // // |-----------|-----------| - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // second_context_id - // ); - // assert_eq!(grid.contexts()[current_index].down, None); - // } - - // #[test] - // fn test_select_current_based_on_mouse() { - // let mut mouse = Mouse::default(); - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.select_current_based_on_mouse(&mouse); - // // On first should always return first item - // assert_eq!(grid.current_index(), 0); - - // grid.split_down(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_height = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current_index(), 1); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - // assert_eq!(grid.current_index(), 2); - // assert_eq!(grid.current().dimension.width, new_context_expected_height); - // assert_eq!(grid.current().dimension.height, 300.); - - // grid.select_current_based_on_mouse(&mouse); - // assert_eq!(grid.current_index(), 0); - // assert_eq!(grid.current().rich_text_id, 0); - - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // mouse.y = (new_context_expected_height + scaled_padding) as usize; - // grid.select_current_based_on_mouse(&mouse); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, second_context_id); - - // mouse.x = 304; - // grid.select_current_based_on_mouse(&mouse); - - // assert_eq!(grid.current_index(), 2); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // } + #[test] + fn test_single_context_respecting_margin_and_no_quad_creation() { + let margin = Delta { + x: 10., + top_y: 20., + bottom_y: 20., + }; + + let context_dimension = ContextDimension::build( + 1200.0, + 800.0, + SugarDimensions { + scale: 2., + width: 18., + height: 9., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 66); + assert_eq!(context_dimension.lines, 88); + let rich_text_id = 1; + let route_id = 0; + let context = create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ); + let context_width = context.dimension.width; + let context_height = context.dimension.height; + let context_margin = context.dimension.margin; + let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); + // The first context should fill completely w/h grid + assert_eq!(grid.width, context_width); + assert_eq!(grid.height, context_height); + + // Context margin should empty + assert_eq!(Delta::::default(), context_margin); + assert_eq!(grid.margin, margin); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: rich_text_id, + position: [10., 20.], + })] + ); + } + + #[test] + fn test_split_right() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 1200.0, + 800.0, + SugarDimensions { + scale: 1., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 85); + assert_eq!(context_dimension.lines, 100); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + grid.split_right(second_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + Object::RichText(RichText { + id: second_context_id, + position: [600., 0.0] + }), + create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + ] + ); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + Object::RichText(RichText { + id: second_context_id, + position: [600.0, 0.0] + }), + create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), + Object::RichText(RichText { + id: third_context_id, + position: [900.0, 0.0] + }), + create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + ] + ); + } + + #[test] + fn test_split_right_with_margin() { + let margin = Delta { + x: 20., + top_y: 30., + bottom_y: 40., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + })] + ); + grid.split_right(second_context); + + /* + > before split: + 20 (600/20) + |------| + + Available width should compute with margin + so should be 600 - 20 = 580, then will be: + 289 + 4 (PADDING) + 290 + + > after split: + 10 (289/0) (4) (290/10) + |----------|----------| + + Margin should be splitted between first columns + items and last columns items + */ + + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 290.); + assert_eq!(contexts[1].val.dimension.margin.x, 10.); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + }), + create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: second_context_id, + position: [167.0, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [145.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [312.0, margin.top_y], [1.0, 300.0]), + ] + ); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + }), + create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: second_context_id, + position: [167.0, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [65.5, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [232.5, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: third_context_id, + position: [236.5, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [236.5, 330.0], [67.5, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [304.0, margin.top_y], [1.0, 300.0]), + ] + ); + + // Last context should be updated with half of x + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 131.); + assert_eq!(contexts[1].val.dimension.margin.x, 0.); + assert_eq!(contexts[2].val.dimension.width, 135.); + assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.select_prev_split(); + grid.split_right(fourth_context); + + // If the split right happens in not the last + // then should not update margin to half of x + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 51.5); + assert_eq!(contexts[1].val.dimension.margin.x, 0.); + assert_eq!(contexts[3].val.dimension.width, 55.5); + assert_eq!(contexts[3].val.dimension.margin.x, 0.); + + // 2 is the last one + assert_eq!(contexts[2].val.dimension.width, 135.0); + assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + }), + create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: second_context_id, + position: [167.0, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [25.75, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: fourth_context_id, + position: [196.75, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.0], [27.75, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: third_context_id, + position: [228.5, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.0], [67.5, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), + ] + ); + } + + #[test] + fn test_split_right_with_margin_inside_parent() { + let margin = Delta { + x: 20., + top_y: 30., + bottom_y: 40., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + })] + ); + + let (third_context, _third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, _fourth_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fifth_context, _fifth_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(second_context); + grid.select_prev_split(); + grid.split_down(third_context); + grid.split_right(fourth_context); + grid.split_right(fifth_context); + + // If the split right happens in not the last + // then should not update margin to half of x + + assert_eq!(grid.current_index(), 4); + + // |1.--------------|2.------------| + // |3.----|4.--|5.--|--------------| + let contexts = grid.contexts(); + assert_eq!(contexts.len(), 5); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 290.); + assert_eq!(contexts[1].val.dimension.margin.x, 10.); + assert_eq!(contexts[2].val.dimension.width, 129.0); + assert_eq!(contexts[2].val.dimension.margin.x, 0.); + assert_eq!(contexts[3].val.dimension.width, 52.5); + assert_eq!(contexts[3].val.dimension.margin.x, 0.); + assert_eq!(contexts[4].val.dimension.width, 56.5); + + // Fifth context should not have any margin x + // TODO: + // assert_eq!(contexts[4].val.dimension.margin.x, 0.); + + grid.remove_current(); + assert_eq!(grid.current_index(), 3); + let contexts = grid.contexts(); + assert_eq!(contexts[1].val.dimension.margin.x, 10.); + // Fourth context should not have any margin x + // TODO: + // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + } + + #[test] + fn test_split_down_with_margin_inside_parent() { + let margin = Delta { + x: 20., + top_y: 30., + bottom_y: 40., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 1., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (third_context, third_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 4; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fifth_context, fifth_context_id) = { + let rich_text_id = 5; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + })] + ); + + grid.split_down(second_context); + grid.split_down(third_context); + grid.split_right(fourth_context); + grid.select_prev_split(); + grid.select_prev_split(); + let current_index = grid.current_index(); + let contexts = grid.contexts(); + assert_eq!(contexts[current_index].val.rich_text_id, second_context_id); + grid.split_right(fifth_context); + + // If the split right happens in not the last + // then should not update margin to half of x + + assert_eq!(grid.current_index(), 4); + + // |1.--------------| + // |2.------|5.-----| + // |3.------|4.-----| + let contexts = grid.contexts(); + assert_eq!(contexts.len(), 5); + + assert_eq!(contexts[0].val.rich_text_id, first_context_id); + assert_eq!(contexts[0].val.dimension.height, 298.); + assert_eq!(contexts[0].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[0].val.dimension.margin.bottom_y, 0.); + let first_down = contexts[0].down; + assert_eq!(first_down, Some(1)); + assert_eq!( + contexts[first_down.unwrap_or_default()].val.rich_text_id, + second_context_id + ); + + assert_eq!(contexts[1].val.rich_text_id, second_context_id); + assert_eq!(contexts[1].val.dimension.height, 148.); + assert_eq!(contexts[1].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[1].val.dimension.margin.bottom_y, 0.); + + assert_eq!(contexts[4].val.rich_text_id, fifth_context_id); + assert_eq!(contexts[4].val.dimension.height, 148.0); + assert_eq!(contexts[4].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[4].val.dimension.margin.bottom_y, 0.); + + assert_eq!(contexts[2].val.rich_text_id, third_context_id); + assert_eq!(contexts[2].val.dimension.height, 150.0); + assert_eq!(contexts[2].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[2].val.dimension.margin.bottom_y, 40.); + + assert_eq!(contexts[3].val.rich_text_id, fourth_context_id); + assert_eq!(contexts[3].val.dimension.height, 150.0); + assert_eq!(contexts[3].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[3].val.dimension.margin.bottom_y, 40.); + + // Fifth context should not have any margin x + // TODO: Removal + // grid.remove_current(); + } + + #[test] + // https://github.com/raphamorim/rio/issues/760 + fn test_split_issue_760() { + let width = 1200.; + let height = 800.; + + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + width, + height, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 85); + assert_eq!(context_dimension.lines, 100); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + grid.split_down(second_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + Object::RichText(RichText { + id: second_context_id, + position: [0.0, 202.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + ] + ); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, first_context_id); + assert_eq!(grid.current_index(), 0); + grid.split_right(third_context); + assert_eq!(grid.current().rich_text_id, third_context_id); + assert_eq!(grid.current_index(), 2); + + let contexts = grid.contexts(); + + let scaled_padding = PADDING * contexts[0].val.dimension.dimension.scale; + + // Check their respective width + assert_eq!( + contexts[0].val.dimension.width, + (width / 2.) - scaled_padding + ); + assert_eq!(contexts[1].val.dimension.width, width); + assert_eq!(contexts[2].val.dimension.width, width / 2.); + + // Check their respective height + let top_height = (height / 2.) - scaled_padding; + assert_eq!(contexts[0].val.dimension.height, top_height); + assert_eq!(contexts[1].val.dimension.height, height / 2.); + assert_eq!(contexts[2].val.dimension.height, top_height); + + // [RichText(RichText { id: 0, position: [0.0, 0.0] }), + // Rect(Rect { position: [298.0, 0.0], color: [0.0, 0.0, 1.0, 0.0], size: [1.0, 396.0] }), + // RichText(RichText { id: 2, position: [302.0, 0.0] }), + // Rect(Rect { position: [0.0, 198.0], color: [0.0, 0.0, 1.0, 0.0], size: [596.0, 1.0] }), + // RichText(RichText { id: 1, position: [0.0, 202.0] })] + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [298.0, 1.0]), + Object::RichText(RichText { + id: second_context_id, + position: [0.0, 202.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + create_border([0.0, 0.0, 1.0, 0.0], [298.0, 0.0], [1.0, 198.0]), + Object::RichText(RichText { + id: third_context_id, + position: [302.0, 0.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [302.0, 198.0], [300.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [602.0, 0.0], [1.0, 198.0]), + ] + ); + } + + #[test] + fn test_remove_right_with_margin() { + let margin = Delta { + x: 20., + top_y: 30., + bottom_y: 40., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + })] + ); + grid.split_right(second_context); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + + let first_expected_dimension = (286., 0.); + let second_expected_dimension = (131., 0.); + let third_expected_dimension = (135., 10.); + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); + assert_eq!( + contexts[0].val.dimension.margin.x, + first_expected_dimension.1 + ); + assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); + assert_eq!( + contexts[1].val.dimension.margin.x, + second_expected_dimension.1 + ); + assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); + assert_eq!( + contexts[2].val.dimension.margin.x, + third_expected_dimension.1 + ); + + grid.select_prev_split(); + grid.split_right(fourth_context); + + // If the split right happens in not the last + // then should not update margin to half of x + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 51.5); + assert_eq!(contexts[1].val.dimension.margin.x, 0.); + assert_eq!(contexts[3].val.dimension.width, 55.5); + assert_eq!(contexts[3].val.dimension.margin.x, 0.); + + // 2 is the last one + assert_eq!(contexts[2].val.dimension.width, 135.0); + assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + }), + create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.], [143.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: second_context_id, + position: [167.0, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.], [25.75, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: fourth_context_id, + position: [196.75, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.], [27.75, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: third_context_id, + position: [228.5, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.], [67.5, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), + ] + ); + + grid.remove_current(); + + // If the split right happens in not the last + // then should not update margin to half of x + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); + assert_eq!( + contexts[0].val.dimension.margin.x, + first_expected_dimension.1 + ); + assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); + assert_eq!( + contexts[1].val.dimension.margin.x, + second_expected_dimension.1 + ); + assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); + assert_eq!( + contexts[2].val.dimension.margin.x, + third_expected_dimension.1 + ); + + assert_eq!(grid.current_index(), 1); + grid.select_next_split(); + assert_eq!(grid.current_index(), 2); + + // Margin x should move to last + grid.remove_current(); + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 290.); + assert_eq!(contexts[1].val.dimension.margin.x, 10.); + } + + #[test] + fn test_split_down() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 1200.0, + 800.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 85); + assert_eq!(context_dimension.lines, 100); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + grid.split_down(second_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + Object::RichText(RichText { + id: second_context_id, + position: [0.0, 202.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + ] + ); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_down(third_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + Object::RichText(RichText { + id: second_context_id, + position: [0.0, 202.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 300.0], [600.0, 1.0]), + Object::RichText(RichText { + id: third_context_id, + position: [0.0, 304.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 404.0], [600.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 304.0], [1.0, 100.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 98.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + ] + ); + } + + #[test] + fn test_resize() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (third_context, _third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_right(second_context); + grid.split_down(third_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // Object::Rect(Rect { + // position: [147.0, 0.0], + // color: [0.0, 0.0, 0.0, 0.0], + // size: [1.0, 300.0] + // }), + // Object::RichText(RichText { + // id: second_context_id, + // position: [149.0, 0.0] + // }), + // Object::Rect(Rect { + // position: [149.0, 147.0], + // color: [0.0, 0.0, 0.0, 0.0], + // size: [294.0, 1.0] + // }), + // Object::RichText(RichText { + // id: third_context_id, + // position: [149.0, 149.0] + // }), + // ] + // ); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + grid.resize(1200.0, 600.0); + + // TODO: Finish test + } + + #[test] + fn test_remove_right_without_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + assert_eq!(grid.current().dimension.width, 600.); + + grid.split_right(second_context); + + let new_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.width, new_expected_width); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + let old_expected_width = (600. / 2.) - scaled_padding; + assert_eq!(grid.current().dimension.width, old_expected_width); + assert_eq!(grid.current_index(), 0); + + grid.select_next_split(); + assert_eq!(grid.current_index(), 1); + + grid.remove_current(); + + assert_eq!(grid.current_index(), 0); + // Whenever return to one should drop padding + assert_eq!(grid.current().dimension.width, 600.); + } + + #[test] + fn test_remove_right_with_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_right(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + let old_context_expected_width = (600. / 2.) - scaled_padding; + assert_eq!(grid.current().dimension.width, old_context_expected_width); + assert_eq!(grid.current_index(), 0); + + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].right, Some(1)); + assert_eq!(grid.contexts()[current_index].down, None); + + grid.remove_current(); + + assert_eq!(grid.current_index(), 0); + // Whenever return to one should drop padding + let expected_width = 600.; + assert_eq!(grid.current().dimension.width, expected_width); + + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].right, None); + assert_eq!(grid.contexts()[current_index].down, None); + } + + #[test] + fn test_remove_right_with_down_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_right(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current_index(), 1); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_down(third_context); + assert_eq!(grid.current_index(), 2); + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current().dimension.height, 300.); + + // Move back + grid.select_prev_split(); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, second_context_id); + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current().dimension.height, 296.); + + // Remove the current should actually make right being down + grid.remove_current(); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, third_context_id); + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current().dimension.height, 600.); + } + + #[test] + fn test_remove_down_without_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + assert_eq!(grid.current().dimension.width, 600.); + + grid.split_down(second_context); + + let new_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_expected_width); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + let old_expected_width = (600. / 2.) - scaled_padding; + assert_eq!(grid.current().dimension.height, old_expected_width); + assert_eq!(grid.current_index(), 0); + + grid.select_next_split(); + assert_eq!(grid.current_index(), 1); + + grid.remove_current(); + + assert_eq!(grid.current_index(), 0); + // Whenever return to one should drop padding + assert_eq!(grid.current().dimension.height, 600.); + } + + #[test] + fn test_remove_down_with_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_down(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_height = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + let old_context_expected_height = (600. / 2.) - scaled_padding; + assert_eq!(grid.current().dimension.height, old_context_expected_height); + assert_eq!(grid.current_index(), 0); + + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].down, Some(1)); + assert_eq!(grid.contexts()[current_index].right, None); + + grid.remove_current(); + + assert_eq!(grid.current_index(), 0); + // Whenever return to one should drop padding + let expected_height = 600.; + assert_eq!(grid.current().dimension.height, expected_height); + + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].down, None); + assert_eq!(grid.contexts()[current_index].right, None); + } + + #[test] + fn test_remove_down_with_right_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_down(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_height = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current_index(), 1); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + assert_eq!(grid.current_index(), 2); + assert_eq!(grid.current().dimension.width, new_context_expected_height); + assert_eq!(grid.current().dimension.height, 300.); + + // Move back + grid.select_prev_split(); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, second_context_id); + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current().dimension.width, 296.); + + // Remove the current should actually make down being down + grid.remove_current(); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, third_context_id); + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current().dimension.width, 600.); + } + + #[test] + fn test_remove_context_with_parent_but_down_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (third_context, third_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 4; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fifth_context, fifth_context_id) = { + let rich_text_id = 5; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (sixth_context, sixth_context_id) = { + let rich_text_id = 6; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + // The test is to validate the removal of a context with parenting however + // should move to up the down items + // + // Test setup + // + // |1.-----|.3-----|4.-----| + // |2.-----|.5-|6.-|-------| + + grid.split_down(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_height = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current().rich_text_id, second_context_id); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, first_context_id); + + grid.split_right(third_context); + assert_eq!(grid.current().rich_text_id, third_context_id); + + grid.split_right(fourth_context); + assert_eq!(grid.current().rich_text_id, fourth_context_id); + + let current_index = grid.current_index(); + assert_eq!(current_index, 3); + assert_eq!(grid.contexts()[current_index].down, None); + + // So far we have: + // + // |1.-----|.3-----|4.-----| + // |2.-----|-------|-------| + + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, third_context_id); + let current_index = grid.current_index(); + assert_eq!(current_index, 2); + assert_eq!(grid.contexts()[current_index].down, None); + + grid.split_down(fifth_context); + assert_eq!(grid.current().rich_text_id, fifth_context_id); + + grid.split_right(sixth_context); + assert_eq!(grid.current().rich_text_id, sixth_context_id); + + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + + assert_eq!(grid.current().rich_text_id, third_context_id); + + let current_index = grid.current_index(); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + fourth_context_id + ); + let current_index = grid.current_index(); + let down = grid.contexts()[current_index].down; + assert_eq!( + grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + fifth_context_id + ); + // Setup complete, now we have 3 as active as well + // + // |1.-----|.3-----|4.-----| + // |2.-----|.5-|6.-|-------| + // + // If we remove 3 then should be + // + // |1.-----|.5-|6.-|4.-----| + // |2.-----|---|---|-------| + + grid.remove_current(); + + // Check if current is 5 and next is 6 + assert_eq!(grid.current().rich_text_id, fifth_context_id); + let current_index = grid.current_index(); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + sixth_context_id + ); + + // Let's go back to 1 to check if leads to 5 + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + + assert_eq!(grid.current().rich_text_id, first_context_id); + let current_index = grid.current_index(); + assert_eq!(current_index, 0); + let right = grid.contexts()[current_index].right; + assert_eq!(right, Some(3)); + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + fifth_context_id + ); + + // Let's go to 6 to check if leads to 4 + // + // |1.-----|.5-|6.-|4.-----| + // |2.-----|---|---|-------| + + grid.select_next_split(); + grid.select_next_split(); + grid.select_next_split(); + grid.select_next_split(); + + assert_eq!(grid.current().rich_text_id, sixth_context_id); + let current_index = grid.current_index(); + let right = grid.contexts()[current_index].right; + assert_eq!(right, Some(2)); + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + fourth_context_id + ); + } + + #[test] + fn test_remove_context_without_parents_but_with_right_and_down_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (third_context, third_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 4; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_right(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current().rich_text_id, second_context_id); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, second_context_id); + + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, first_context_id); + + grid.split_down(third_context); + assert_eq!(grid.current().rich_text_id, third_context_id); + assert_eq!(grid.current().dimension.width, 296.); + assert_eq!(grid.current().dimension.height, 300.); + + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, second_context_id); + grid.split_down(fourth_context); + + assert_eq!(grid.current_index(), 3); + assert_eq!(grid.current().rich_text_id, fourth_context_id); + + grid.select_next_split(); + assert_eq!(grid.current_index(), 0); + assert_eq!(grid.current().rich_text_id, first_context_id); + + // Active is 1 + // |1.----|.2----| + // |3.----|.4----| + + // Remove the current should actually make right being down + grid.remove_current(); + let current_index = grid.current_index(); + // Move third context to first position + assert_eq!(current_index, 0); + assert_eq!(grid.current().rich_text_id, third_context_id); + let right = grid.contexts()[current_index].right; + let right_context = grid.contexts()[right.unwrap_or_default()].val.rich_text_id; + assert_eq!(right_context, second_context_id); + + // Result: + // |3.----|.2----| + // |------|.4----| + + // Now let's create a more complex case + // |3.---------|.2---------| + // |5.-|6.-|7.-|.4---------| + + let (fifth_context, fifth_context_id) = { + let rich_text_id = 5; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (sixth_context, sixth_context_id) = { + let rich_text_id = 6; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (seventh_context, seventh_context_id) = { + let rich_text_id = 7; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_down(fifth_context); + grid.split_right(sixth_context); + grid.split_right(seventh_context); + + assert_eq!(grid.current_index(), 5); + assert_eq!(grid.current().rich_text_id, seventh_context_id); + + // Current: + // |3.---------|.2---------| + // |5.-|6.-|7.-|.4---------| + // + // Now if we move back to 3. and remove it: + // Should move 5, 6 and 7 to top. + // + // |5.-|6.-|7.-|.2---------| + // |---|---|---|.4---------| + grid.select_next_split(); + assert_eq!(grid.current().rich_text_id, third_context_id); + let current_index = grid.current_index(); + let down = grid.contexts()[current_index].down; + assert_eq!( + grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + fifth_context_id + ); + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, fifth_context_id); + + let current_index = grid.current_index(); + let right = grid.contexts()[current_index].right.unwrap_or_default(); + let right_context = &grid.contexts()[right]; + assert_eq!(right_context.val.rich_text_id, sixth_context_id); + + // Current: + // |5.-|6.-|7.-|.2---------| + // |---|---|---|.4---------| + + // Ok, let's test the reverse to right operations + // First remove 5 and 6 + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, sixth_context_id); + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].down, None); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + seventh_context_id + ); + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, seventh_context_id); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + second_context_id + ); + + // Current: + // |7.---------|.2---------| + // |-----------|.4---------| + + // Now let's add many 5 and 6 as down items on 7th + // + // Should be: + // |7.---------|.2---------| + // |5.---------|.4---------| + // |6.---------|-----------| + + let (fifth_context, fifth_context_id) = { + let rich_text_id = 5; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (sixth_context, sixth_context_id) = { + let rich_text_id = 6; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_down(fifth_context); + grid.split_down(sixth_context); + + assert_eq!(grid.current().rich_text_id, sixth_context_id); + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, fifth_context_id); + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, seventh_context_id); + + // Next step remove 7 + // + // Should be: + // |5.---------|.2---------| + // |6.---------|.4---------| + // |-----------|-----------| + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, fifth_context_id); + let right = grid.contexts()[current_index].right; + let down = grid.contexts()[current_index].down; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + second_context_id + ); + assert_eq!( + grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + sixth_context_id + ); + + // Next step remove 5 + // + // Should be: + // |6.---------|.2---------| + // |-----------|.4---------| + // |-----------|-----------| + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, sixth_context_id); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + second_context_id + ); + assert_eq!(grid.contexts()[current_index].down, None); + } + + #[test] + fn test_select_current_based_on_mouse() { + let mut mouse = Mouse::default(); + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.select_current_based_on_mouse(&mouse); + // On first should always return first item + assert_eq!(grid.current_index(), 0); + + grid.split_down(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_height = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current_index(), 1); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + assert_eq!(grid.current_index(), 2); + assert_eq!(grid.current().dimension.width, new_context_expected_height); + assert_eq!(grid.current().dimension.height, 300.); + + grid.select_current_based_on_mouse(&mouse); + assert_eq!(grid.current_index(), 0); + assert_eq!(grid.current().rich_text_id, 0); + + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + mouse.y = (new_context_expected_height + scaled_padding) as usize; + grid.select_current_based_on_mouse(&mouse); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, second_context_id); + + mouse.x = 304; + grid.select_current_based_on_mouse(&mouse); + + assert_eq!(grid.current_index(), 2); + assert_eq!(grid.current().rich_text_id, third_context_id); + } } From ce8474647211cc6b5e05b9fe741c36b6a0324e36 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Fri, 20 Dec 2024 22:12:16 -0300 Subject: [PATCH 04/20] remove grid and keep context/mod.rs tests --- frontends/rioterm/src/context/grid.rs | 5228 ++++++++++++------------- frontends/rioterm/src/context/mod.rs | 370 +- 2 files changed, 2799 insertions(+), 2799 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index de49be4807..f9189bd42e 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -969,2618 +969,2618 @@ pub mod test { use pretty_assertions::assert_eq; use rio_window::window::WindowId; - #[test] - fn test_single_context_respecting_margin_and_no_quad_creation() { - let margin = Delta { - x: 10., - top_y: 20., - bottom_y: 20., - }; - - let context_dimension = ContextDimension::build( - 1200.0, - 800.0, - SugarDimensions { - scale: 2., - width: 18., - height: 9., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 66); - assert_eq!(context_dimension.lines, 88); - let rich_text_id = 1; - let route_id = 0; - let context = create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ); - let context_width = context.dimension.width; - let context_height = context.dimension.height; - let context_margin = context.dimension.margin; - let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); - // The first context should fill completely w/h grid - assert_eq!(grid.width, context_width); - assert_eq!(grid.height, context_height); - - // Context margin should empty - assert_eq!(Delta::::default(), context_margin); - assert_eq!(grid.margin, margin); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: rich_text_id, - position: [10., 20.], - })] - ); - } - - #[test] - fn test_split_right() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 1200.0, - 800.0, - SugarDimensions { - scale: 1., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 85); - assert_eq!(context_dimension.lines, 100); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - grid.split_right(second_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - Object::RichText(RichText { - id: second_context_id, - position: [600., 0.0] - }), - create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - ] - ); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - Object::RichText(RichText { - id: second_context_id, - position: [600.0, 0.0] - }), - create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), - Object::RichText(RichText { - id: third_context_id, - position: [900.0, 0.0] - }), - create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - ] - ); - } - - #[test] - fn test_split_right_with_margin() { - let margin = Delta { - x: 20., - top_y: 30., - bottom_y: 40., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - })] - ); - grid.split_right(second_context); - - /* - > before split: - 20 (600/20) - |------| - - Available width should compute with margin - so should be 600 - 20 = 580, then will be: - 289 + 4 (PADDING) + 290 - - > after split: - 10 (289/0) (4) (290/10) - |----------|----------| - - Margin should be splitted between first columns - items and last columns items - */ - - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 290.); - assert_eq!(contexts[1].val.dimension.margin.x, 10.); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - }), - create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: second_context_id, - position: [167.0, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [145.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [312.0, margin.top_y], [1.0, 300.0]), - ] - ); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - }), - create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: second_context_id, - position: [167.0, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [65.5, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [232.5, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: third_context_id, - position: [236.5, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [236.5, 330.0], [67.5, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [304.0, margin.top_y], [1.0, 300.0]), - ] - ); - - // Last context should be updated with half of x - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 131.); - assert_eq!(contexts[1].val.dimension.margin.x, 0.); - assert_eq!(contexts[2].val.dimension.width, 135.); - assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.select_prev_split(); - grid.split_right(fourth_context); - - // If the split right happens in not the last - // then should not update margin to half of x - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 51.5); - assert_eq!(contexts[1].val.dimension.margin.x, 0.); - assert_eq!(contexts[3].val.dimension.width, 55.5); - assert_eq!(contexts[3].val.dimension.margin.x, 0.); - - // 2 is the last one - assert_eq!(contexts[2].val.dimension.width, 135.0); - assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - }), - create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: second_context_id, - position: [167.0, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [25.75, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: fourth_context_id, - position: [196.75, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.0], [27.75, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: third_context_id, - position: [228.5, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.0], [67.5, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), - ] - ); - } - - #[test] - fn test_split_right_with_margin_inside_parent() { - let margin = Delta { - x: 20., - top_y: 30., - bottom_y: 40., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - })] - ); - - let (third_context, _third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, _fourth_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fifth_context, _fifth_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(second_context); - grid.select_prev_split(); - grid.split_down(third_context); - grid.split_right(fourth_context); - grid.split_right(fifth_context); - - // If the split right happens in not the last - // then should not update margin to half of x - - assert_eq!(grid.current_index(), 4); - - // |1.--------------|2.------------| - // |3.----|4.--|5.--|--------------| - let contexts = grid.contexts(); - assert_eq!(contexts.len(), 5); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 290.); - assert_eq!(contexts[1].val.dimension.margin.x, 10.); - assert_eq!(contexts[2].val.dimension.width, 129.0); - assert_eq!(contexts[2].val.dimension.margin.x, 0.); - assert_eq!(contexts[3].val.dimension.width, 52.5); - assert_eq!(contexts[3].val.dimension.margin.x, 0.); - assert_eq!(contexts[4].val.dimension.width, 56.5); - - // Fifth context should not have any margin x - // TODO: - // assert_eq!(contexts[4].val.dimension.margin.x, 0.); - - grid.remove_current(); - assert_eq!(grid.current_index(), 3); - let contexts = grid.contexts(); - assert_eq!(contexts[1].val.dimension.margin.x, 10.); - // Fourth context should not have any margin x - // TODO: - // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - } - - #[test] - fn test_split_down_with_margin_inside_parent() { - let margin = Delta { - x: 20., - top_y: 30., - bottom_y: 40., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 1., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (third_context, third_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 4; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fifth_context, fifth_context_id) = { - let rich_text_id = 5; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - })] - ); - - grid.split_down(second_context); - grid.split_down(third_context); - grid.split_right(fourth_context); - grid.select_prev_split(); - grid.select_prev_split(); - let current_index = grid.current_index(); - let contexts = grid.contexts(); - assert_eq!(contexts[current_index].val.rich_text_id, second_context_id); - grid.split_right(fifth_context); - - // If the split right happens in not the last - // then should not update margin to half of x - - assert_eq!(grid.current_index(), 4); - - // |1.--------------| - // |2.------|5.-----| - // |3.------|4.-----| - let contexts = grid.contexts(); - assert_eq!(contexts.len(), 5); - - assert_eq!(contexts[0].val.rich_text_id, first_context_id); - assert_eq!(contexts[0].val.dimension.height, 298.); - assert_eq!(contexts[0].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[0].val.dimension.margin.bottom_y, 0.); - let first_down = contexts[0].down; - assert_eq!(first_down, Some(1)); - assert_eq!( - contexts[first_down.unwrap_or_default()].val.rich_text_id, - second_context_id - ); - - assert_eq!(contexts[1].val.rich_text_id, second_context_id); - assert_eq!(contexts[1].val.dimension.height, 148.); - assert_eq!(contexts[1].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[1].val.dimension.margin.bottom_y, 0.); - - assert_eq!(contexts[4].val.rich_text_id, fifth_context_id); - assert_eq!(contexts[4].val.dimension.height, 148.0); - assert_eq!(contexts[4].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[4].val.dimension.margin.bottom_y, 0.); - - assert_eq!(contexts[2].val.rich_text_id, third_context_id); - assert_eq!(contexts[2].val.dimension.height, 150.0); - assert_eq!(contexts[2].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[2].val.dimension.margin.bottom_y, 40.); - - assert_eq!(contexts[3].val.rich_text_id, fourth_context_id); - assert_eq!(contexts[3].val.dimension.height, 150.0); - assert_eq!(contexts[3].val.dimension.margin.top_y, 0.); - assert_eq!(contexts[3].val.dimension.margin.bottom_y, 40.); - - // Fifth context should not have any margin x - // TODO: Removal - // grid.remove_current(); - } - - #[test] - // https://github.com/raphamorim/rio/issues/760 - fn test_split_issue_760() { - let width = 1200.; - let height = 800.; - - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - width, - height, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 85); - assert_eq!(context_dimension.lines, 100); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - grid.split_down(second_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - Object::RichText(RichText { - id: second_context_id, - position: [0.0, 202.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - ] - ); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, first_context_id); - assert_eq!(grid.current_index(), 0); - grid.split_right(third_context); - assert_eq!(grid.current().rich_text_id, third_context_id); - assert_eq!(grid.current_index(), 2); - - let contexts = grid.contexts(); - - let scaled_padding = PADDING * contexts[0].val.dimension.dimension.scale; - - // Check their respective width - assert_eq!( - contexts[0].val.dimension.width, - (width / 2.) - scaled_padding - ); - assert_eq!(contexts[1].val.dimension.width, width); - assert_eq!(contexts[2].val.dimension.width, width / 2.); - - // Check their respective height - let top_height = (height / 2.) - scaled_padding; - assert_eq!(contexts[0].val.dimension.height, top_height); - assert_eq!(contexts[1].val.dimension.height, height / 2.); - assert_eq!(contexts[2].val.dimension.height, top_height); - - // [RichText(RichText { id: 0, position: [0.0, 0.0] }), - // Rect(Rect { position: [298.0, 0.0], color: [0.0, 0.0, 1.0, 0.0], size: [1.0, 396.0] }), - // RichText(RichText { id: 2, position: [302.0, 0.0] }), - // Rect(Rect { position: [0.0, 198.0], color: [0.0, 0.0, 1.0, 0.0], size: [596.0, 1.0] }), - // RichText(RichText { id: 1, position: [0.0, 202.0] })] - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [298.0, 1.0]), - Object::RichText(RichText { - id: second_context_id, - position: [0.0, 202.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - create_border([0.0, 0.0, 1.0, 0.0], [298.0, 0.0], [1.0, 198.0]), - Object::RichText(RichText { - id: third_context_id, - position: [302.0, 0.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [302.0, 198.0], [300.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [602.0, 0.0], [1.0, 198.0]), - ] - ); - } - - #[test] - fn test_remove_right_with_margin() { - let margin = Delta { - x: 20., - top_y: 30., - bottom_y: 40., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - })] - ); - grid.split_right(second_context); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - - let first_expected_dimension = (286., 0.); - let second_expected_dimension = (131., 0.); - let third_expected_dimension = (135., 10.); - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); - assert_eq!( - contexts[0].val.dimension.margin.x, - first_expected_dimension.1 - ); - assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); - assert_eq!( - contexts[1].val.dimension.margin.x, - second_expected_dimension.1 - ); - assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); - assert_eq!( - contexts[2].val.dimension.margin.x, - third_expected_dimension.1 - ); - - grid.select_prev_split(); - grid.split_right(fourth_context); - - // If the split right happens in not the last - // then should not update margin to half of x - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 51.5); - assert_eq!(contexts[1].val.dimension.margin.x, 0.); - assert_eq!(contexts[3].val.dimension.width, 55.5); - assert_eq!(contexts[3].val.dimension.margin.x, 0.); - - // 2 is the last one - assert_eq!(contexts[2].val.dimension.width, 135.0); - assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [margin.x, margin.top_y], - }), - create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.], [143.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: second_context_id, - position: [167.0, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.], [25.75, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: fourth_context_id, - position: [196.75, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.], [27.75, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), - Object::RichText(RichText { - id: third_context_id, - position: [228.5, margin.top_y] - }), - create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.], [67.5, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), - ] - ); - - grid.remove_current(); - - // If the split right happens in not the last - // then should not update margin to half of x - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); - assert_eq!( - contexts[0].val.dimension.margin.x, - first_expected_dimension.1 - ); - assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); - assert_eq!( - contexts[1].val.dimension.margin.x, - second_expected_dimension.1 - ); - assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); - assert_eq!( - contexts[2].val.dimension.margin.x, - third_expected_dimension.1 - ); - - assert_eq!(grid.current_index(), 1); - grid.select_next_split(); - assert_eq!(grid.current_index(), 2); - - // Margin x should move to last - grid.remove_current(); - let contexts = grid.contexts(); - assert_eq!(contexts[0].val.dimension.width, 286.); - assert_eq!(contexts[0].val.dimension.margin.x, 0.); - assert_eq!(contexts[1].val.dimension.width, 290.); - assert_eq!(contexts[1].val.dimension.margin.x, 10.); - } - - #[test] - fn test_split_down() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 1200.0, - 800.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 85); - assert_eq!(context_dimension.lines, 100); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - grid.split_down(second_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - Object::RichText(RichText { - id: second_context_id, - position: [0.0, 202.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - ] - ); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_down(third_context); - - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - Object::RichText(RichText { - id: second_context_id, - position: [0.0, 202.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 300.0], [600.0, 1.0]), - Object::RichText(RichText { - id: third_context_id, - position: [0.0, 304.0] - }), - create_border([0.0, 0.0, 1.0, 0.0], [0.0, 404.0], [600.0, 1.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 304.0], [1.0, 100.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 98.0]), - create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - ] - ); - } - - #[test] - fn test_resize() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (third_context, _third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_right(second_context); - grid.split_down(third_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // Object::Rect(Rect { - // position: [147.0, 0.0], - // color: [0.0, 0.0, 0.0, 0.0], - // size: [1.0, 300.0] - // }), - // Object::RichText(RichText { - // id: second_context_id, - // position: [149.0, 0.0] - // }), - // Object::Rect(Rect { - // position: [149.0, 147.0], - // color: [0.0, 0.0, 0.0, 0.0], - // size: [294.0, 1.0] - // }), - // Object::RichText(RichText { - // id: third_context_id, - // position: [149.0, 149.0] - // }), - // ] - // ); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - grid.resize(1200.0, 600.0); - - // TODO: Finish test - } - - #[test] - fn test_remove_right_without_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - assert_eq!(grid.current().dimension.width, 600.); - - grid.split_right(second_context); - - let new_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.width, new_expected_width); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - let old_expected_width = (600. / 2.) - scaled_padding; - assert_eq!(grid.current().dimension.width, old_expected_width); - assert_eq!(grid.current_index(), 0); - - grid.select_next_split(); - assert_eq!(grid.current_index(), 1); - - grid.remove_current(); - - assert_eq!(grid.current_index(), 0); - // Whenever return to one should drop padding - assert_eq!(grid.current().dimension.width, 600.); - } - - #[test] - fn test_remove_right_with_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_right(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - let old_context_expected_width = (600. / 2.) - scaled_padding; - assert_eq!(grid.current().dimension.width, old_context_expected_width); - assert_eq!(grid.current_index(), 0); - - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].right, Some(1)); - assert_eq!(grid.contexts()[current_index].down, None); - - grid.remove_current(); - - assert_eq!(grid.current_index(), 0); - // Whenever return to one should drop padding - let expected_width = 600.; - assert_eq!(grid.current().dimension.width, expected_width); - - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].right, None); - assert_eq!(grid.contexts()[current_index].down, None); - } - - #[test] - fn test_remove_right_with_down_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_right(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current_index(), 1); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_down(third_context); - assert_eq!(grid.current_index(), 2); - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current().dimension.height, 300.); - - // Move back - grid.select_prev_split(); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, second_context_id); - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current().dimension.height, 296.); - - // Remove the current should actually make right being down - grid.remove_current(); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, third_context_id); - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current().dimension.height, 600.); - } - - #[test] - fn test_remove_down_without_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - assert_eq!(grid.current().dimension.width, 600.); - - grid.split_down(second_context); - - let new_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_expected_width); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - let old_expected_width = (600. / 2.) - scaled_padding; - assert_eq!(grid.current().dimension.height, old_expected_width); - assert_eq!(grid.current_index(), 0); - - grid.select_next_split(); - assert_eq!(grid.current_index(), 1); - - grid.remove_current(); - - assert_eq!(grid.current_index(), 0); - // Whenever return to one should drop padding - assert_eq!(grid.current().dimension.height, 600.); - } - - #[test] - fn test_remove_down_with_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, _second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_down(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_height = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - let old_context_expected_height = (600. / 2.) - scaled_padding; - assert_eq!(grid.current().dimension.height, old_context_expected_height); - assert_eq!(grid.current_index(), 0); - - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].down, Some(1)); - assert_eq!(grid.contexts()[current_index].right, None); - - grid.remove_current(); - - assert_eq!(grid.current_index(), 0); - // Whenever return to one should drop padding - let expected_height = 600.; - assert_eq!(grid.current().dimension.height, expected_height); - - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].down, None); - assert_eq!(grid.contexts()[current_index].right, None); - } - - #[test] - fn test_remove_down_with_right_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_down(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_height = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current_index(), 1); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - assert_eq!(grid.current_index(), 2); - assert_eq!(grid.current().dimension.width, new_context_expected_height); - assert_eq!(grid.current().dimension.height, 300.); - - // Move back - grid.select_prev_split(); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, second_context_id); - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current().dimension.width, 296.); - - // Remove the current should actually make down being down - grid.remove_current(); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, third_context_id); - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current().dimension.width, 600.); - } - - #[test] - fn test_remove_context_with_parent_but_down_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (third_context, third_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 4; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fifth_context, fifth_context_id) = { - let rich_text_id = 5; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (sixth_context, sixth_context_id) = { - let rich_text_id = 6; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - // The test is to validate the removal of a context with parenting however - // should move to up the down items - // - // Test setup - // - // |1.-----|.3-----|4.-----| - // |2.-----|.5-|6.-|-------| - - grid.split_down(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_height = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current().rich_text_id, second_context_id); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, first_context_id); - - grid.split_right(third_context); - assert_eq!(grid.current().rich_text_id, third_context_id); - - grid.split_right(fourth_context); - assert_eq!(grid.current().rich_text_id, fourth_context_id); - - let current_index = grid.current_index(); - assert_eq!(current_index, 3); - assert_eq!(grid.contexts()[current_index].down, None); - - // So far we have: - // - // |1.-----|.3-----|4.-----| - // |2.-----|-------|-------| - - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, third_context_id); - let current_index = grid.current_index(); - assert_eq!(current_index, 2); - assert_eq!(grid.contexts()[current_index].down, None); - - grid.split_down(fifth_context); - assert_eq!(grid.current().rich_text_id, fifth_context_id); - - grid.split_right(sixth_context); - assert_eq!(grid.current().rich_text_id, sixth_context_id); - - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - - assert_eq!(grid.current().rich_text_id, third_context_id); - - let current_index = grid.current_index(); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - fourth_context_id - ); - let current_index = grid.current_index(); - let down = grid.contexts()[current_index].down; - assert_eq!( - grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - fifth_context_id - ); - // Setup complete, now we have 3 as active as well - // - // |1.-----|.3-----|4.-----| - // |2.-----|.5-|6.-|-------| - // - // If we remove 3 then should be - // - // |1.-----|.5-|6.-|4.-----| - // |2.-----|---|---|-------| - - grid.remove_current(); - - // Check if current is 5 and next is 6 - assert_eq!(grid.current().rich_text_id, fifth_context_id); - let current_index = grid.current_index(); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - sixth_context_id - ); - - // Let's go back to 1 to check if leads to 5 - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - - assert_eq!(grid.current().rich_text_id, first_context_id); - let current_index = grid.current_index(); - assert_eq!(current_index, 0); - let right = grid.contexts()[current_index].right; - assert_eq!(right, Some(3)); - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - fifth_context_id - ); - - // Let's go to 6 to check if leads to 4 - // - // |1.-----|.5-|6.-|4.-----| - // |2.-----|---|---|-------| - - grid.select_next_split(); - grid.select_next_split(); - grid.select_next_split(); - grid.select_next_split(); - - assert_eq!(grid.current().rich_text_id, sixth_context_id); - let current_index = grid.current_index(); - let right = grid.contexts()[current_index].right; - assert_eq!(right, Some(2)); - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - fourth_context_id - ); - } - - #[test] - fn test_remove_context_without_parents_but_with_right_and_down_children() { - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (third_context, third_context_id) = { - let rich_text_id = 3; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (fourth_context, fourth_context_id) = { - let rich_text_id = 4; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.split_right(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_width = 600. / 2.; - - assert_eq!(grid.current().dimension.width, new_context_expected_width); - assert_eq!(grid.current().rich_text_id, second_context_id); - assert_eq!(grid.current_index(), 1); - - grid.select_prev_split(); - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, second_context_id); - - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, first_context_id); - - grid.split_down(third_context); - assert_eq!(grid.current().rich_text_id, third_context_id); - assert_eq!(grid.current().dimension.width, 296.); - assert_eq!(grid.current().dimension.height, 300.); - - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, second_context_id); - grid.split_down(fourth_context); - - assert_eq!(grid.current_index(), 3); - assert_eq!(grid.current().rich_text_id, fourth_context_id); - - grid.select_next_split(); - assert_eq!(grid.current_index(), 0); - assert_eq!(grid.current().rich_text_id, first_context_id); - - // Active is 1 - // |1.----|.2----| - // |3.----|.4----| - - // Remove the current should actually make right being down - grid.remove_current(); - let current_index = grid.current_index(); - // Move third context to first position - assert_eq!(current_index, 0); - assert_eq!(grid.current().rich_text_id, third_context_id); - let right = grid.contexts()[current_index].right; - let right_context = grid.contexts()[right.unwrap_or_default()].val.rich_text_id; - assert_eq!(right_context, second_context_id); - - // Result: - // |3.----|.2----| - // |------|.4----| - - // Now let's create a more complex case - // |3.---------|.2---------| - // |5.-|6.-|7.-|.4---------| - - let (fifth_context, fifth_context_id) = { - let rich_text_id = 5; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (sixth_context, sixth_context_id) = { - let rich_text_id = 6; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (seventh_context, seventh_context_id) = { - let rich_text_id = 7; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_down(fifth_context); - grid.split_right(sixth_context); - grid.split_right(seventh_context); - - assert_eq!(grid.current_index(), 5); - assert_eq!(grid.current().rich_text_id, seventh_context_id); - - // Current: - // |3.---------|.2---------| - // |5.-|6.-|7.-|.4---------| - // - // Now if we move back to 3. and remove it: - // Should move 5, 6 and 7 to top. - // - // |5.-|6.-|7.-|.2---------| - // |---|---|---|.4---------| - grid.select_next_split(); - assert_eq!(grid.current().rich_text_id, third_context_id); - let current_index = grid.current_index(); - let down = grid.contexts()[current_index].down; - assert_eq!( - grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - fifth_context_id - ); - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, fifth_context_id); - - let current_index = grid.current_index(); - let right = grid.contexts()[current_index].right.unwrap_or_default(); - let right_context = &grid.contexts()[right]; - assert_eq!(right_context.val.rich_text_id, sixth_context_id); - - // Current: - // |5.-|6.-|7.-|.2---------| - // |---|---|---|.4---------| - - // Ok, let's test the reverse to right operations - // First remove 5 and 6 - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, sixth_context_id); - let current_index = grid.current_index(); - assert_eq!(grid.contexts()[current_index].down, None); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - seventh_context_id - ); - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, seventh_context_id); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - second_context_id - ); - - // Current: - // |7.---------|.2---------| - // |-----------|.4---------| - - // Now let's add many 5 and 6 as down items on 7th - // - // Should be: - // |7.---------|.2---------| - // |5.---------|.4---------| - // |6.---------|-----------| - - let (fifth_context, fifth_context_id) = { - let rich_text_id = 5; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (sixth_context, sixth_context_id) = { - let rich_text_id = 6; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_down(fifth_context); - grid.split_down(sixth_context); - - assert_eq!(grid.current().rich_text_id, sixth_context_id); - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, fifth_context_id); - grid.select_prev_split(); - grid.select_prev_split(); - grid.select_prev_split(); - assert_eq!(grid.current().rich_text_id, seventh_context_id); - - // Next step remove 7 - // - // Should be: - // |5.---------|.2---------| - // |6.---------|.4---------| - // |-----------|-----------| - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, fifth_context_id); - let right = grid.contexts()[current_index].right; - let down = grid.contexts()[current_index].down; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - second_context_id - ); - assert_eq!( - grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - sixth_context_id - ); - - // Next step remove 5 - // - // Should be: - // |6.---------|.2---------| - // |-----------|.4---------| - // |-----------|-----------| - - grid.remove_current(); - assert_eq!(grid.current().rich_text_id, sixth_context_id); - let right = grid.contexts()[current_index].right; - assert_eq!( - grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - second_context_id - ); - assert_eq!(grid.contexts()[current_index].down, None); - } - - #[test] - fn test_select_current_based_on_mouse() { - let mut mouse = Mouse::default(); - let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., - }; - - let context_dimension = ContextDimension::build( - 600.0, - 600.0, - SugarDimensions { - scale: 2., - width: 14., - height: 8., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 42); - assert_eq!(context_dimension.lines, 75); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], - })] - ); - - grid.select_current_based_on_mouse(&mouse); - // On first should always return first item - assert_eq!(grid.current_index(), 0); - - grid.split_down(second_context); - - assert_eq!(grid.width, 600.0); - assert_eq!(grid.height, 600.0); - - let new_context_expected_height = 600. / 2.; - - assert_eq!(grid.current().dimension.height, new_context_expected_height); - assert_eq!(grid.current_index(), 1); - - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - grid.split_right(third_context); - assert_eq!(grid.current_index(), 2); - assert_eq!(grid.current().dimension.width, new_context_expected_height); - assert_eq!(grid.current().dimension.height, 300.); - - grid.select_current_based_on_mouse(&mouse); - assert_eq!(grid.current_index(), 0); - assert_eq!(grid.current().rich_text_id, 0); - - let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - mouse.y = (new_context_expected_height + scaled_padding) as usize; - grid.select_current_based_on_mouse(&mouse); - - assert_eq!(grid.current_index(), 1); - assert_eq!(grid.current().rich_text_id, second_context_id); - - mouse.x = 304; - grid.select_current_based_on_mouse(&mouse); - - assert_eq!(grid.current_index(), 2); - assert_eq!(grid.current().rich_text_id, third_context_id); - } + // #[test] + // fn test_single_context_respecting_margin_and_no_quad_creation() { + // let margin = Delta { + // x: 10., + // top_y: 20., + // bottom_y: 20., + // }; + + // let context_dimension = ContextDimension::build( + // 1200.0, + // 800.0, + // SugarDimensions { + // scale: 2., + // width: 18., + // height: 9., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 66); + // assert_eq!(context_dimension.lines, 88); + // let rich_text_id = 1; + // let route_id = 0; + // let context = create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ); + // let context_width = context.dimension.width; + // let context_height = context.dimension.height; + // let context_margin = context.dimension.margin; + // let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); + // // The first context should fill completely w/h grid + // assert_eq!(grid.width, context_width); + // assert_eq!(grid.height, context_height); + + // // Context margin should empty + // assert_eq!(Delta::::default(), context_margin); + // assert_eq!(grid.margin, margin); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: rich_text_id, + // position: [10., 20.], + // })] + // ); + // } + + // #[test] + // fn test_split_right() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 1200.0, + // 800.0, + // SugarDimensions { + // scale: 1., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 85); + // assert_eq!(context_dimension.lines, 100); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + // grid.split_right(second_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [600., 0.0] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + // ] + // ); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [600.0, 0.0] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [900.0, 0.0] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + // ] + // ); + // } + + // #[test] + // fn test_split_right_with_margin() { + // let margin = Delta { + // x: 20., + // top_y: 30., + // bottom_y: 40., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // })] + // ); + // grid.split_right(second_context); + + // /* + // > before split: + // 20 (600/20) + // |------| + + // Available width should compute with margin + // so should be 600 - 20 = 580, then will be: + // 289 + 4 (PADDING) + 290 + + // > after split: + // 10 (289/0) (4) (290/10) + // |----------|----------| + + // Margin should be splitted between first columns + // items and last columns items + // */ + + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 290.); + // assert_eq!(contexts[1].val.dimension.margin.x, 10.); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [167.0, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [145.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [312.0, margin.top_y], [1.0, 300.0]), + // ] + // ); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [167.0, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [65.5, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [232.5, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [236.5, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [236.5, 330.0], [67.5, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [304.0, margin.top_y], [1.0, 300.0]), + // ] + // ); + + // // Last context should be updated with half of x + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 131.); + // assert_eq!(contexts[1].val.dimension.margin.x, 0.); + // assert_eq!(contexts[2].val.dimension.width, 135.); + // assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.select_prev_split(); + // grid.split_right(fourth_context); + + // // If the split right happens in not the last + // // then should not update margin to half of x + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 51.5); + // assert_eq!(contexts[1].val.dimension.margin.x, 0.); + // assert_eq!(contexts[3].val.dimension.width, 55.5); + // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + + // // 2 is the last one + // assert_eq!(contexts[2].val.dimension.width, 135.0); + // assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [167.0, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [25.75, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: fourth_context_id, + // position: [196.75, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.0], [27.75, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [228.5, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.0], [67.5, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), + // ] + // ); + // } + + // #[test] + // fn test_split_right_with_margin_inside_parent() { + // let margin = Delta { + // x: 20., + // top_y: 30., + // bottom_y: 40., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // })] + // ); + + // let (third_context, _third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, _fourth_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fifth_context, _fifth_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(second_context); + // grid.select_prev_split(); + // grid.split_down(third_context); + // grid.split_right(fourth_context); + // grid.split_right(fifth_context); + + // // If the split right happens in not the last + // // then should not update margin to half of x + + // assert_eq!(grid.current_index(), 4); + + // // |1.--------------|2.------------| + // // |3.----|4.--|5.--|--------------| + // let contexts = grid.contexts(); + // assert_eq!(contexts.len(), 5); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 290.); + // assert_eq!(contexts[1].val.dimension.margin.x, 10.); + // assert_eq!(contexts[2].val.dimension.width, 129.0); + // assert_eq!(contexts[2].val.dimension.margin.x, 0.); + // assert_eq!(contexts[3].val.dimension.width, 52.5); + // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + // assert_eq!(contexts[4].val.dimension.width, 56.5); + + // // Fifth context should not have any margin x + // // TODO: + // // assert_eq!(contexts[4].val.dimension.margin.x, 0.); + + // grid.remove_current(); + // assert_eq!(grid.current_index(), 3); + // let contexts = grid.contexts(); + // assert_eq!(contexts[1].val.dimension.margin.x, 10.); + // // Fourth context should not have any margin x + // // TODO: + // // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + // } + + // #[test] + // fn test_split_down_with_margin_inside_parent() { + // let margin = Delta { + // x: 20., + // top_y: 30., + // bottom_y: 40., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 1., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (third_context, third_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 4; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fifth_context, fifth_context_id) = { + // let rich_text_id = 5; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // })] + // ); + + // grid.split_down(second_context); + // grid.split_down(third_context); + // grid.split_right(fourth_context); + // grid.select_prev_split(); + // grid.select_prev_split(); + // let current_index = grid.current_index(); + // let contexts = grid.contexts(); + // assert_eq!(contexts[current_index].val.rich_text_id, second_context_id); + // grid.split_right(fifth_context); + + // // If the split right happens in not the last + // // then should not update margin to half of x + + // assert_eq!(grid.current_index(), 4); + + // // |1.--------------| + // // |2.------|5.-----| + // // |3.------|4.-----| + // let contexts = grid.contexts(); + // assert_eq!(contexts.len(), 5); + + // assert_eq!(contexts[0].val.rich_text_id, first_context_id); + // assert_eq!(contexts[0].val.dimension.height, 298.); + // assert_eq!(contexts[0].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[0].val.dimension.margin.bottom_y, 0.); + // let first_down = contexts[0].down; + // assert_eq!(first_down, Some(1)); + // assert_eq!( + // contexts[first_down.unwrap_or_default()].val.rich_text_id, + // second_context_id + // ); + + // assert_eq!(contexts[1].val.rich_text_id, second_context_id); + // assert_eq!(contexts[1].val.dimension.height, 148.); + // assert_eq!(contexts[1].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[1].val.dimension.margin.bottom_y, 0.); + + // assert_eq!(contexts[4].val.rich_text_id, fifth_context_id); + // assert_eq!(contexts[4].val.dimension.height, 148.0); + // assert_eq!(contexts[4].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[4].val.dimension.margin.bottom_y, 0.); + + // assert_eq!(contexts[2].val.rich_text_id, third_context_id); + // assert_eq!(contexts[2].val.dimension.height, 150.0); + // assert_eq!(contexts[2].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[2].val.dimension.margin.bottom_y, 40.); + + // assert_eq!(contexts[3].val.rich_text_id, fourth_context_id); + // assert_eq!(contexts[3].val.dimension.height, 150.0); + // assert_eq!(contexts[3].val.dimension.margin.top_y, 0.); + // assert_eq!(contexts[3].val.dimension.margin.bottom_y, 40.); + + // // Fifth context should not have any margin x + // // TODO: Removal + // // grid.remove_current(); + // } + + // #[test] + // // https://github.com/raphamorim/rio/issues/760 + // fn test_split_issue_760() { + // let width = 1200.; + // let height = 800.; + + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // width, + // height, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 85); + // assert_eq!(context_dimension.lines, 100); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + // grid.split_down(second_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [0.0, 202.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + // ] + // ); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, first_context_id); + // assert_eq!(grid.current_index(), 0); + // grid.split_right(third_context); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // assert_eq!(grid.current_index(), 2); + + // let contexts = grid.contexts(); + + // let scaled_padding = PADDING * contexts[0].val.dimension.dimension.scale; + + // // Check their respective width + // assert_eq!( + // contexts[0].val.dimension.width, + // (width / 2.) - scaled_padding + // ); + // assert_eq!(contexts[1].val.dimension.width, width); + // assert_eq!(contexts[2].val.dimension.width, width / 2.); + + // // Check their respective height + // let top_height = (height / 2.) - scaled_padding; + // assert_eq!(contexts[0].val.dimension.height, top_height); + // assert_eq!(contexts[1].val.dimension.height, height / 2.); + // assert_eq!(contexts[2].val.dimension.height, top_height); + + // // [RichText(RichText { id: 0, position: [0.0, 0.0] }), + // // Rect(Rect { position: [298.0, 0.0], color: [0.0, 0.0, 1.0, 0.0], size: [1.0, 396.0] }), + // // RichText(RichText { id: 2, position: [302.0, 0.0] }), + // // Rect(Rect { position: [0.0, 198.0], color: [0.0, 0.0, 1.0, 0.0], size: [596.0, 1.0] }), + // // RichText(RichText { id: 1, position: [0.0, 202.0] })] + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [298.0, 1.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [0.0, 202.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [298.0, 0.0], [1.0, 198.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [302.0, 0.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [302.0, 198.0], [300.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [602.0, 0.0], [1.0, 198.0]), + // ] + // ); + // } + + // #[test] + // fn test_remove_right_with_margin() { + // let margin = Delta { + // x: 20., + // top_y: 30., + // bottom_y: 40., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // })] + // ); + // grid.split_right(second_context); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + + // let first_expected_dimension = (286., 0.); + // let second_expected_dimension = (131., 0.); + // let third_expected_dimension = (135., 10.); + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); + // assert_eq!( + // contexts[0].val.dimension.margin.x, + // first_expected_dimension.1 + // ); + // assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); + // assert_eq!( + // contexts[1].val.dimension.margin.x, + // second_expected_dimension.1 + // ); + // assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); + // assert_eq!( + // contexts[2].val.dimension.margin.x, + // third_expected_dimension.1 + // ); + + // grid.select_prev_split(); + // grid.split_right(fourth_context); + + // // If the split right happens in not the last + // // then should not update margin to half of x + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 51.5); + // assert_eq!(contexts[1].val.dimension.margin.x, 0.); + // assert_eq!(contexts[3].val.dimension.width, 55.5); + // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + + // // 2 is the last one + // assert_eq!(contexts[2].val.dimension.width, 135.0); + // assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [margin.x, margin.top_y], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.], [143.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [167.0, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.], [25.75, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: fourth_context_id, + // position: [196.75, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.], [27.75, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [228.5, margin.top_y] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.], [67.5, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), + // ] + // ); + + // grid.remove_current(); + + // // If the split right happens in not the last + // // then should not update margin to half of x + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); + // assert_eq!( + // contexts[0].val.dimension.margin.x, + // first_expected_dimension.1 + // ); + // assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); + // assert_eq!( + // contexts[1].val.dimension.margin.x, + // second_expected_dimension.1 + // ); + // assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); + // assert_eq!( + // contexts[2].val.dimension.margin.x, + // third_expected_dimension.1 + // ); + + // assert_eq!(grid.current_index(), 1); + // grid.select_next_split(); + // assert_eq!(grid.current_index(), 2); + + // // Margin x should move to last + // grid.remove_current(); + // let contexts = grid.contexts(); + // assert_eq!(contexts[0].val.dimension.width, 286.); + // assert_eq!(contexts[0].val.dimension.margin.x, 0.); + // assert_eq!(contexts[1].val.dimension.width, 290.); + // assert_eq!(contexts[1].val.dimension.margin.x, 10.); + // } + + // #[test] + // fn test_split_down() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 1200.0, + // 800.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 85); + // assert_eq!(context_dimension.lines, 100); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + // grid.split_down(second_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [0.0, 202.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + // ] + // ); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_down(third_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [0.0, 202.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 300.0], [600.0, 1.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [0.0, 304.0] + // }), + // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 404.0], [600.0, 1.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 304.0], [1.0, 100.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 98.0]), + // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + // ] + // ); + // } + + // #[test] + // fn test_resize() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (third_context, _third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_right(second_context); + // grid.split_down(third_context); + + // // assert_eq!( + // // grid.objects(), + // // vec![ + // // Object::RichText(RichText { + // // id: first_context_id, + // // position: [0.0, 0.0], + // // }), + // // Object::Rect(Rect { + // // position: [147.0, 0.0], + // // color: [0.0, 0.0, 0.0, 0.0], + // // size: [1.0, 300.0] + // // }), + // // Object::RichText(RichText { + // // id: second_context_id, + // // position: [149.0, 0.0] + // // }), + // // Object::Rect(Rect { + // // position: [149.0, 147.0], + // // color: [0.0, 0.0, 0.0, 0.0], + // // size: [294.0, 1.0] + // // }), + // // Object::RichText(RichText { + // // id: third_context_id, + // // position: [149.0, 149.0] + // // }), + // // ] + // // ); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // grid.resize(1200.0, 600.0); + + // // TODO: Finish test + // } + + // #[test] + // fn test_remove_right_without_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + // assert_eq!(grid.current().dimension.width, 600.); + + // grid.split_right(second_context); + + // let new_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.width, new_expected_width); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // let old_expected_width = (600. / 2.) - scaled_padding; + // assert_eq!(grid.current().dimension.width, old_expected_width); + // assert_eq!(grid.current_index(), 0); + + // grid.select_next_split(); + // assert_eq!(grid.current_index(), 1); + + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 0); + // // Whenever return to one should drop padding + // assert_eq!(grid.current().dimension.width, 600.); + // } + + // #[test] + // fn test_remove_right_with_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_right(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // let old_context_expected_width = (600. / 2.) - scaled_padding; + // assert_eq!(grid.current().dimension.width, old_context_expected_width); + // assert_eq!(grid.current_index(), 0); + + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].right, Some(1)); + // assert_eq!(grid.contexts()[current_index].down, None); + + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 0); + // // Whenever return to one should drop padding + // let expected_width = 600.; + // assert_eq!(grid.current().dimension.width, expected_width); + + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].right, None); + // assert_eq!(grid.contexts()[current_index].down, None); + // } + + // #[test] + // fn test_remove_right_with_down_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_right(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current_index(), 1); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_down(third_context); + // assert_eq!(grid.current_index(), 2); + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current().dimension.height, 300.); + + // // Move back + // grid.select_prev_split(); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current().dimension.height, 296.); + + // // Remove the current should actually make right being down + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current().dimension.height, 600.); + // } + + // #[test] + // fn test_remove_down_without_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + // assert_eq!(grid.current().dimension.width, 600.); + + // grid.split_down(second_context); + + // let new_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_expected_width); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // let old_expected_width = (600. / 2.) - scaled_padding; + // assert_eq!(grid.current().dimension.height, old_expected_width); + // assert_eq!(grid.current_index(), 0); + + // grid.select_next_split(); + // assert_eq!(grid.current_index(), 1); + + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 0); + // // Whenever return to one should drop padding + // assert_eq!(grid.current().dimension.height, 600.); + // } + + // #[test] + // fn test_remove_down_with_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, _second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_down(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_height = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // let old_context_expected_height = (600. / 2.) - scaled_padding; + // assert_eq!(grid.current().dimension.height, old_context_expected_height); + // assert_eq!(grid.current_index(), 0); + + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].down, Some(1)); + // assert_eq!(grid.contexts()[current_index].right, None); + + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 0); + // // Whenever return to one should drop padding + // let expected_height = 600.; + // assert_eq!(grid.current().dimension.height, expected_height); + + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].down, None); + // assert_eq!(grid.contexts()[current_index].right, None); + // } + + // #[test] + // fn test_remove_down_with_right_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_down(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_height = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current_index(), 1); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + // assert_eq!(grid.current_index(), 2); + // assert_eq!(grid.current().dimension.width, new_context_expected_height); + // assert_eq!(grid.current().dimension.height, 300.); + + // // Move back + // grid.select_prev_split(); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current().dimension.width, 296.); + + // // Remove the current should actually make down being down + // grid.remove_current(); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current().dimension.width, 600.); + // } + + // #[test] + // fn test_remove_context_with_parent_but_down_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (third_context, third_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 4; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fifth_context, fifth_context_id) = { + // let rich_text_id = 5; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (sixth_context, sixth_context_id) = { + // let rich_text_id = 6; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // // The test is to validate the removal of a context with parenting however + // // should move to up the down items + // // + // // Test setup + // // + // // |1.-----|.3-----|4.-----| + // // |2.-----|.5-|6.-|-------| + + // grid.split_down(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_height = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, first_context_id); + + // grid.split_right(third_context); + // assert_eq!(grid.current().rich_text_id, third_context_id); + + // grid.split_right(fourth_context); + // assert_eq!(grid.current().rich_text_id, fourth_context_id); + + // let current_index = grid.current_index(); + // assert_eq!(current_index, 3); + // assert_eq!(grid.contexts()[current_index].down, None); + + // // So far we have: + // // + // // |1.-----|.3-----|4.-----| + // // |2.-----|-------|-------| + + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // let current_index = grid.current_index(); + // assert_eq!(current_index, 2); + // assert_eq!(grid.contexts()[current_index].down, None); + + // grid.split_down(fifth_context); + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + + // grid.split_right(sixth_context); + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + + // assert_eq!(grid.current().rich_text_id, third_context_id); + + // let current_index = grid.current_index(); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // fourth_context_id + // ); + // let current_index = grid.current_index(); + // let down = grid.contexts()[current_index].down; + // assert_eq!( + // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + // fifth_context_id + // ); + // // Setup complete, now we have 3 as active as well + // // + // // |1.-----|.3-----|4.-----| + // // |2.-----|.5-|6.-|-------| + // // + // // If we remove 3 then should be + // // + // // |1.-----|.5-|6.-|4.-----| + // // |2.-----|---|---|-------| + + // grid.remove_current(); + + // // Check if current is 5 and next is 6 + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + // let current_index = grid.current_index(); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // sixth_context_id + // ); + + // // Let's go back to 1 to check if leads to 5 + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + + // assert_eq!(grid.current().rich_text_id, first_context_id); + // let current_index = grid.current_index(); + // assert_eq!(current_index, 0); + // let right = grid.contexts()[current_index].right; + // assert_eq!(right, Some(3)); + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // fifth_context_id + // ); + + // // Let's go to 6 to check if leads to 4 + // // + // // |1.-----|.5-|6.-|4.-----| + // // |2.-----|---|---|-------| + + // grid.select_next_split(); + // grid.select_next_split(); + // grid.select_next_split(); + // grid.select_next_split(); + + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + // let current_index = grid.current_index(); + // let right = grid.contexts()[current_index].right; + // assert_eq!(right, Some(2)); + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // fourth_context_id + // ); + // } + + // #[test] + // fn test_remove_context_without_parents_but_with_right_and_down_children() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (third_context, third_context_id) = { + // let rich_text_id = 3; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (fourth_context, fourth_context_id) = { + // let rich_text_id = 4; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.split_right(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_width = 600. / 2.; + + // assert_eq!(grid.current().dimension.width, new_context_expected_width); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // assert_eq!(grid.current_index(), 1); + + // grid.select_prev_split(); + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, second_context_id); + + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, first_context_id); + + // grid.split_down(third_context); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // assert_eq!(grid.current().dimension.width, 296.); + // assert_eq!(grid.current().dimension.height, 300.); + + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, second_context_id); + // grid.split_down(fourth_context); + + // assert_eq!(grid.current_index(), 3); + // assert_eq!(grid.current().rich_text_id, fourth_context_id); + + // grid.select_next_split(); + // assert_eq!(grid.current_index(), 0); + // assert_eq!(grid.current().rich_text_id, first_context_id); + + // // Active is 1 + // // |1.----|.2----| + // // |3.----|.4----| + + // // Remove the current should actually make right being down + // grid.remove_current(); + // let current_index = grid.current_index(); + // // Move third context to first position + // assert_eq!(current_index, 0); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // let right = grid.contexts()[current_index].right; + // let right_context = grid.contexts()[right.unwrap_or_default()].val.rich_text_id; + // assert_eq!(right_context, second_context_id); + + // // Result: + // // |3.----|.2----| + // // |------|.4----| + + // // Now let's create a more complex case + // // |3.---------|.2---------| + // // |5.-|6.-|7.-|.4---------| + + // let (fifth_context, fifth_context_id) = { + // let rich_text_id = 5; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (sixth_context, sixth_context_id) = { + // let rich_text_id = 6; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (seventh_context, seventh_context_id) = { + // let rich_text_id = 7; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_down(fifth_context); + // grid.split_right(sixth_context); + // grid.split_right(seventh_context); + + // assert_eq!(grid.current_index(), 5); + // assert_eq!(grid.current().rich_text_id, seventh_context_id); + + // // Current: + // // |3.---------|.2---------| + // // |5.-|6.-|7.-|.4---------| + // // + // // Now if we move back to 3. and remove it: + // // Should move 5, 6 and 7 to top. + // // + // // |5.-|6.-|7.-|.2---------| + // // |---|---|---|.4---------| + // grid.select_next_split(); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // let current_index = grid.current_index(); + // let down = grid.contexts()[current_index].down; + // assert_eq!( + // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + // fifth_context_id + // ); + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + + // let current_index = grid.current_index(); + // let right = grid.contexts()[current_index].right.unwrap_or_default(); + // let right_context = &grid.contexts()[right]; + // assert_eq!(right_context.val.rich_text_id, sixth_context_id); + + // // Current: + // // |5.-|6.-|7.-|.2---------| + // // |---|---|---|.4---------| + + // // Ok, let's test the reverse to right operations + // // First remove 5 and 6 + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + // let current_index = grid.current_index(); + // assert_eq!(grid.contexts()[current_index].down, None); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // seventh_context_id + // ); + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, seventh_context_id); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // second_context_id + // ); + + // // Current: + // // |7.---------|.2---------| + // // |-----------|.4---------| + + // // Now let's add many 5 and 6 as down items on 7th + // // + // // Should be: + // // |7.---------|.2---------| + // // |5.---------|.4---------| + // // |6.---------|-----------| + + // let (fifth_context, fifth_context_id) = { + // let rich_text_id = 5; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (sixth_context, sixth_context_id) = { + // let rich_text_id = 6; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_down(fifth_context); + // grid.split_down(sixth_context); + + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + // grid.select_prev_split(); + // grid.select_prev_split(); + // grid.select_prev_split(); + // assert_eq!(grid.current().rich_text_id, seventh_context_id); + + // // Next step remove 7 + // // + // // Should be: + // // |5.---------|.2---------| + // // |6.---------|.4---------| + // // |-----------|-----------| + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, fifth_context_id); + // let right = grid.contexts()[current_index].right; + // let down = grid.contexts()[current_index].down; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // second_context_id + // ); + // assert_eq!( + // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + // sixth_context_id + // ); + + // // Next step remove 5 + // // + // // Should be: + // // |6.---------|.2---------| + // // |-----------|.4---------| + // // |-----------|-----------| + + // grid.remove_current(); + // assert_eq!(grid.current().rich_text_id, sixth_context_id); + // let right = grid.contexts()[current_index].right; + // assert_eq!( + // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + // second_context_id + // ); + // assert_eq!(grid.contexts()[current_index].down, None); + // } + + // #[test] + // fn test_select_current_based_on_mouse() { + // let mut mouse = Mouse::default(); + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; + + // let context_dimension = ContextDimension::build( + // 600.0, + // 600.0, + // SugarDimensions { + // scale: 2., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); + + // assert_eq!(context_dimension.columns, 42); + // assert_eq!(context_dimension.lines, 75); + + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + + // grid.select_current_based_on_mouse(&mouse); + // // On first should always return first item + // assert_eq!(grid.current_index(), 0); + + // grid.split_down(second_context); + + // assert_eq!(grid.width, 600.0); + // assert_eq!(grid.height, 600.0); + + // let new_context_expected_height = 600. / 2.; + + // assert_eq!(grid.current().dimension.height, new_context_expected_height); + // assert_eq!(grid.current_index(), 1); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + // assert_eq!(grid.current_index(), 2); + // assert_eq!(grid.current().dimension.width, new_context_expected_height); + // assert_eq!(grid.current().dimension.height, 300.); + + // grid.select_current_based_on_mouse(&mouse); + // assert_eq!(grid.current_index(), 0); + // assert_eq!(grid.current().rich_text_id, 0); + + // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + // mouse.y = (new_context_expected_height + scaled_padding) as usize; + // grid.select_current_based_on_mouse(&mouse); + + // assert_eq!(grid.current_index(), 1); + // assert_eq!(grid.current().rich_text_id, second_context_id); + + // mouse.x = 304; + // grid.select_current_based_on_mouse(&mouse); + + // assert_eq!(grid.current_index(), 2); + // assert_eq!(grid.current().rich_text_id, third_context_id); + // } } diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index 8541630300..f1e54e9630 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -1059,189 +1059,189 @@ pub mod test { use super::*; use crate::event::VoidListener; - // #[test] - // fn test_capacity() { - // let window_id: WindowId = WindowId::from(0); - - // let context_manager = - // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - // assert_eq!(context_manager.capacity, 5); - - // let mut context_manager = - // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - // context_manager.increase_capacity(3); - // assert_eq!(context_manager.capacity, 8); - // } - - // #[test] - // fn test_add_context() { - // let window_id: WindowId = WindowId::from(0); - - // let mut context_manager = - // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - // assert_eq!(context_manager.capacity, 5); - // assert_eq!(context_manager.current_index, 0); - - // let should_redirect = false; - // context_manager.add_context(should_redirect, 0); - // assert_eq!(context_manager.capacity, 5); - // assert_eq!(context_manager.current_index, 0); - - // let should_redirect = true; - // context_manager.add_context(should_redirect, 0); - // assert_eq!(context_manager.capacity, 5); - // assert_eq!(context_manager.current_index, 2); - // } - - // #[test] - // fn test_add_context_start_with_capacity_limit() { - // let window_id: WindowId = WindowId::from(0); - - // let mut context_manager = - // ContextManager::start_with_capacity(3, VoidListener {}, window_id).unwrap(); - // assert_eq!(context_manager.capacity, 3); - // assert_eq!(context_manager.current_index, 0); - // let should_redirect = false; - // context_manager.add_context(should_redirect, 0); - // assert_eq!(context_manager.len(), 2); - // context_manager.add_context(should_redirect, 0); - // assert_eq!(context_manager.len(), 3); - - // for _ in 0..20 { - // context_manager.add_context(should_redirect, 0); - // } - - // assert_eq!(context_manager.len(), 3); - // assert_eq!(context_manager.capacity, 3); - // } - - // #[test] - // fn test_set_current() { - // let window_id: WindowId = WindowId::from(0); - - // let mut context_manager = - // ContextManager::start_with_capacity(8, VoidListener {}, window_id).unwrap(); - // let should_redirect = true; - - // context_manager.add_context(should_redirect, 0); - // assert_eq!(context_manager.current_index, 1); - // context_manager.set_current(0); - // assert_eq!(context_manager.current_index, 0); - // assert_eq!(context_manager.len(), 2); - // assert_eq!(context_manager.capacity, 8); - - // let should_redirect = false; - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - // context_manager.set_current(3); - // assert_eq!(context_manager.current_index, 3); - - // context_manager.set_current(8); - // assert_eq!(context_manager.current_index, 3); - // } - - // #[test] - // fn test_close_context() { - // let window_id: WindowId = WindowId::from(0); - - // let mut context_manager = - // ContextManager::start_with_capacity(3, VoidListener {}, window_id).unwrap(); - // let should_redirect = false; - - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - // assert_eq!(context_manager.len(), 3); - - // assert_eq!(context_manager.current_index, 0); - // context_manager.set_current(2); - // assert_eq!(context_manager.current_index, 2); - // context_manager.set_current(0); - - // context_manager.close_current_context(); - // context_manager.set_current(2); - // assert_eq!(context_manager.current_index, 0); - // assert_eq!(context_manager.len(), 2); - // } - - // #[test] - // fn test_close_context_upcoming_ids() { - // let window_id: WindowId = WindowId::from(0); - - // let mut context_manager = - // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - // let should_redirect = false; - - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - - // context_manager.close_current_context(); - // context_manager.close_current_context(); - // context_manager.close_current_context(); - // context_manager.close_current_context(); - - // assert_eq!(context_manager.len(), 1); - // assert_eq!(context_manager.current_index, 0); - - // context_manager.add_context(should_redirect, 0); - - // assert_eq!(context_manager.len(), 2); - // context_manager.set_current(1); - // assert_eq!(context_manager.current_index, 1); - // context_manager.close_current_context(); - // assert_eq!(context_manager.len(), 1); - // assert_eq!(context_manager.current_index, 0); - // } - - // #[test] - // fn test_close_last_context() { - // let window_id: WindowId = WindowId::from(0); - - // let mut context_manager = - // ContextManager::start_with_capacity(2, VoidListener {}, window_id).unwrap(); - // let should_redirect = false; - - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - // assert_eq!(context_manager.len(), 2); - // assert_eq!(context_manager.current_index, 0); - - // context_manager.close_current_context(); - // assert_eq!(context_manager.len(), 1); - - // // Last context should not be closed - // context_manager.close_current_context(); - // assert_eq!(context_manager.len(), 1); - // } - - // #[test] - // fn test_switch_to_next() { - // let window_id: WindowId = WindowId::from(0); - - // let mut context_manager = - // ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); - // let should_redirect = false; - - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - // context_manager.add_context(should_redirect, 0); - // assert_eq!(context_manager.len(), 5); - // assert_eq!(context_manager.current_index, 0); - - // context_manager.switch_to_next(); - // assert_eq!(context_manager.current_index, 1); - // context_manager.switch_to_next(); - // assert_eq!(context_manager.current_index, 2); - // context_manager.switch_to_next(); - // assert_eq!(context_manager.current_index, 3); - // context_manager.switch_to_next(); - // assert_eq!(context_manager.current_index, 4); - // context_manager.switch_to_next(); - // assert_eq!(context_manager.current_index, 0); - // context_manager.switch_to_next(); - // assert_eq!(context_manager.current_index, 1); - // } + #[test] + fn test_capacity() { + let window_id: WindowId = WindowId::from(0); + + let context_manager = + ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + assert_eq!(context_manager.capacity, 5); + + let mut context_manager = + ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + context_manager.increase_capacity(3); + assert_eq!(context_manager.capacity, 8); + } + + #[test] + fn test_add_context() { + let window_id: WindowId = WindowId::from(0); + + let mut context_manager = + ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + assert_eq!(context_manager.capacity, 5); + assert_eq!(context_manager.current_index, 0); + + let should_redirect = false; + context_manager.add_context(should_redirect, 0); + assert_eq!(context_manager.capacity, 5); + assert_eq!(context_manager.current_index, 0); + + let should_redirect = true; + context_manager.add_context(should_redirect, 0); + assert_eq!(context_manager.capacity, 5); + assert_eq!(context_manager.current_index, 2); + } + + #[test] + fn test_add_context_start_with_capacity_limit() { + let window_id: WindowId = WindowId::from(0); + + let mut context_manager = + ContextManager::start_with_capacity(3, VoidListener {}, window_id).unwrap(); + assert_eq!(context_manager.capacity, 3); + assert_eq!(context_manager.current_index, 0); + let should_redirect = false; + context_manager.add_context(should_redirect, 0); + assert_eq!(context_manager.len(), 2); + context_manager.add_context(should_redirect, 0); + assert_eq!(context_manager.len(), 3); + + for _ in 0..20 { + context_manager.add_context(should_redirect, 0); + } + + assert_eq!(context_manager.len(), 3); + assert_eq!(context_manager.capacity, 3); + } + + #[test] + fn test_set_current() { + let window_id: WindowId = WindowId::from(0); + + let mut context_manager = + ContextManager::start_with_capacity(8, VoidListener {}, window_id).unwrap(); + let should_redirect = true; + + context_manager.add_context(should_redirect, 0); + assert_eq!(context_manager.current_index, 1); + context_manager.set_current(0); + assert_eq!(context_manager.current_index, 0); + assert_eq!(context_manager.len(), 2); + assert_eq!(context_manager.capacity, 8); + + let should_redirect = false; + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + context_manager.set_current(3); + assert_eq!(context_manager.current_index, 3); + + context_manager.set_current(8); + assert_eq!(context_manager.current_index, 3); + } + + #[test] + fn test_close_context() { + let window_id: WindowId = WindowId::from(0); + + let mut context_manager = + ContextManager::start_with_capacity(3, VoidListener {}, window_id).unwrap(); + let should_redirect = false; + + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + assert_eq!(context_manager.len(), 3); + + assert_eq!(context_manager.current_index, 0); + context_manager.set_current(2); + assert_eq!(context_manager.current_index, 2); + context_manager.set_current(0); + + context_manager.close_current_context(); + context_manager.set_current(2); + assert_eq!(context_manager.current_index, 0); + assert_eq!(context_manager.len(), 2); + } + + #[test] + fn test_close_context_upcoming_ids() { + let window_id: WindowId = WindowId::from(0); + + let mut context_manager = + ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + let should_redirect = false; + + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + + context_manager.close_current_context(); + context_manager.close_current_context(); + context_manager.close_current_context(); + context_manager.close_current_context(); + + assert_eq!(context_manager.len(), 1); + assert_eq!(context_manager.current_index, 0); + + context_manager.add_context(should_redirect, 0); + + assert_eq!(context_manager.len(), 2); + context_manager.set_current(1); + assert_eq!(context_manager.current_index, 1); + context_manager.close_current_context(); + assert_eq!(context_manager.len(), 1); + assert_eq!(context_manager.current_index, 0); + } + + #[test] + fn test_close_last_context() { + let window_id: WindowId = WindowId::from(0); + + let mut context_manager = + ContextManager::start_with_capacity(2, VoidListener {}, window_id).unwrap(); + let should_redirect = false; + + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + assert_eq!(context_manager.len(), 2); + assert_eq!(context_manager.current_index, 0); + + context_manager.close_current_context(); + assert_eq!(context_manager.len(), 1); + + // Last context should not be closed + context_manager.close_current_context(); + assert_eq!(context_manager.len(), 1); + } + + #[test] + fn test_switch_to_next() { + let window_id: WindowId = WindowId::from(0); + + let mut context_manager = + ContextManager::start_with_capacity(5, VoidListener {}, window_id).unwrap(); + let should_redirect = false; + + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + context_manager.add_context(should_redirect, 0); + assert_eq!(context_manager.len(), 5); + assert_eq!(context_manager.current_index, 0); + + context_manager.switch_to_next(); + assert_eq!(context_manager.current_index, 1); + context_manager.switch_to_next(); + assert_eq!(context_manager.current_index, 2); + context_manager.switch_to_next(); + assert_eq!(context_manager.current_index, 3); + context_manager.switch_to_next(); + assert_eq!(context_manager.current_index, 4); + context_manager.switch_to_next(); + assert_eq!(context_manager.current_index, 0); + context_manager.switch_to_next(); + assert_eq!(context_manager.current_index, 1); + } } From 90bfcdddf877a70f330b5cca91ea13ca96f7a6bb Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Fri, 20 Dec 2024 22:13:19 -0300 Subject: [PATCH 05/20] trigger for every pr --- .github/workflows/nix-build.yml | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 059efb15c6..36088e338f 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -1,23 +1,19 @@ name: Nix Build -on: [push, pull_request] - -# on: -# workflow_dispatch: -# pull_request: -# branches: -# - main -# paths: -# - '**/*.rs' -# - '.github/workflows/nix-build.yml' -# - 'nix/**' -# push: -# branches: -# - main -# paths: -# - '**/*.rs' -# - '.github/workflows/nix-build.yml' -# - 'nix/**' +on: + workflow_dispatch: + pull_request: + paths: + - '**/*.rs' + - '.github/workflows/nix-build.yml' + - 'nix/**' + push: + branches: + - main + paths: + - '**/*.rs' + - '.github/workflows/nix-build.yml' + - 'nix/**' jobs: lints: From 49eda99d0e2368d58ff287483eacf5acbd0ead3f Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Fri, 20 Dec 2024 23:41:55 -0300 Subject: [PATCH 06/20] just enable one test from grid --- frontends/rioterm/src/context/grid.rs | 98 +++++++++++++-------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index f9189bd42e..007976a8b9 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -969,57 +969,57 @@ pub mod test { use pretty_assertions::assert_eq; use rio_window::window::WindowId; - // #[test] - // fn test_single_context_respecting_margin_and_no_quad_creation() { - // let margin = Delta { - // x: 10., - // top_y: 20., - // bottom_y: 20., - // }; - - // let context_dimension = ContextDimension::build( - // 1200.0, - // 800.0, - // SugarDimensions { - // scale: 2., - // width: 18., - // height: 9., - // }, - // 1.0, - // Delta::::default(), - // ); + #[test] + fn test_single_context_respecting_margin_and_no_quad_creation() { + let margin = Delta { + x: 10., + top_y: 20., + bottom_y: 20., + }; - // assert_eq!(context_dimension.columns, 66); - // assert_eq!(context_dimension.lines, 88); - // let rich_text_id = 1; - // let route_id = 0; - // let context = create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ); - // let context_width = context.dimension.width; - // let context_height = context.dimension.height; - // let context_margin = context.dimension.margin; - // let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); - // // The first context should fill completely w/h grid - // assert_eq!(grid.width, context_width); - // assert_eq!(grid.height, context_height); - - // // Context margin should empty - // assert_eq!(Delta::::default(), context_margin); - // assert_eq!(grid.margin, margin); + let context_dimension = ContextDimension::build( + 1200.0, + 800.0, + SugarDimensions { + scale: 2., + width: 18., + height: 9., + }, + 1.0, + Delta::::default(), + ); - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: rich_text_id, - // position: [10., 20.], - // })] - // ); - // } + assert_eq!(context_dimension.columns, 66); + assert_eq!(context_dimension.lines, 88); + let rich_text_id = 1; + let route_id = 0; + let context = create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ); + let context_width = context.dimension.width; + let context_height = context.dimension.height; + let context_margin = context.dimension.margin; + let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); + // The first context should fill completely w/h grid + assert_eq!(grid.width, context_width); + assert_eq!(grid.height, context_height); + + // Context margin should empty + assert_eq!(Delta::::default(), context_margin); + assert_eq!(grid.margin, margin); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: rich_text_id, + position: [10., 20.], + })] + ); + } // #[test] // fn test_split_right() { From 80710ec4f974b55559c4f1ad00c210489c0157aa Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Fri, 20 Dec 2024 23:43:54 -0300 Subject: [PATCH 07/20] figure out if is failing over messenger --- frontends/rioterm/src/context/grid.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index 007976a8b9..9c62df26ed 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -435,7 +435,12 @@ impl ContextGrid { drop(terminal); let winsize = crate::renderer::utils::terminal_dimensions(&self.inner[index].val.dimension); - let _ = self.inner[index].val.messenger.send_resize(winsize); + match self.inner[index].val.messenger.send_resize(winsize) { + Ok(_) => {} + Err(a) => { + println!("{:?}", a); + } + } } pub fn remove_current(&mut self) { From d4e7c1a9e719b0d6b1fff968263eec0dd7bba909 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 00:02:06 -0300 Subject: [PATCH 08/20] remove send_resize on messenger --- frontends/rioterm/src/context/grid.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index 9c62df26ed..e40d2012fa 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -433,14 +433,9 @@ impl ContextGrid { let mut terminal = self.inner[index].val.terminal.lock(); terminal.resize::(self.inner[index].val.dimension); drop(terminal); - let winsize = + let _winsize = crate::renderer::utils::terminal_dimensions(&self.inner[index].val.dimension); - match self.inner[index].val.messenger.send_resize(winsize) { - Ok(_) => {} - Err(a) => { - println!("{:?}", a); - } - } + // let _ = self.inner[index].val.messenger.send_resize(winsize); } pub fn remove_current(&mut self) { From 94e9e9d8e475e4c012d0ae63d5fde530c5b6c104 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 16:03:33 -0300 Subject: [PATCH 09/20] could be the use_fork? --- frontends/rioterm/src/context/grid.rs | 4 ++-- frontends/rioterm/src/context/mod.rs | 34 +++++++++++++-------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index e40d2012fa..007976a8b9 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -433,9 +433,9 @@ impl ContextGrid { let mut terminal = self.inner[index].val.terminal.lock(); terminal.resize::(self.inner[index].val.dimension); drop(terminal); - let _winsize = + let winsize = crate::renderer::utils::terminal_dimensions(&self.inner[index].val.dimension); - // let _ = self.inner[index].val.messenger.send_resize(winsize); + let _ = self.inner[index].val.messenger.send_resize(winsize); } pub fn remove_current(&mut self) { diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index f1e54e9630..807b552e81 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -240,7 +240,7 @@ impl ContextManager { let pty; #[cfg(not(target_os = "windows"))] { - if config.use_fork { + // if config.use_fork { tracing::info!("rio -> teletypewriter: create_pty_with_fork"); pty = match create_pty_with_fork( &Cow::Borrowed(&config.shell.program), @@ -253,22 +253,22 @@ impl ContextManager { return Err(Box::new(err)); } } - } else { - tracing::info!("rio -> teletypewriter: create_pty_with_spawn"); - pty = match create_pty_with_spawn( - &Cow::Borrowed(&config.shell.program), - config.shell.args.clone(), - &config.working_dir, - cols, - rows, - ) { - Ok(created_pty) => created_pty, - Err(err) => { - tracing::error!("{err:?}"); - return Err(Box::new(err)); - } - } - }; + // } else { + // tracing::info!("rio -> teletypewriter: create_pty_with_spawn"); + // pty = match create_pty_with_spawn( + // &Cow::Borrowed(&config.shell.program), + // config.shell.args.clone(), + // &config.working_dir, + // cols, + // rows, + // ) { + // Ok(created_pty) => created_pty, + // Err(err) => { + // tracing::error!("{err:?}"); + // return Err(Box::new(err)); + // } + // } + // }; } #[cfg(not(target_os = "windows"))] From fe681edd87f6d21397b955658a9393ce73831c75 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 16:06:23 -0300 Subject: [PATCH 10/20] let's try to break in parts --- frontends/rioterm/src/context/grid.rs | 56 +++++++++++++-------------- frontends/rioterm/src/context/mod.rs | 34 ++++++++-------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index 007976a8b9..b5535a0214 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -991,34 +991,34 @@ pub mod test { assert_eq!(context_dimension.columns, 66); assert_eq!(context_dimension.lines, 88); - let rich_text_id = 1; - let route_id = 0; - let context = create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ); - let context_width = context.dimension.width; - let context_height = context.dimension.height; - let context_margin = context.dimension.margin; - let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); - // The first context should fill completely w/h grid - assert_eq!(grid.width, context_width); - assert_eq!(grid.height, context_height); - - // Context margin should empty - assert_eq!(Delta::::default(), context_margin); - assert_eq!(grid.margin, margin); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: rich_text_id, - position: [10., 20.], - })] - ); + // let rich_text_id = 1; + // let route_id = 0; + // let context = create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ); + // let context_width = context.dimension.width; + // let context_height = context.dimension.height; + // let context_margin = context.dimension.margin; + // let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); + // // The first context should fill completely w/h grid + // assert_eq!(grid.width, context_width); + // assert_eq!(grid.height, context_height); + + // // Context margin should empty + // assert_eq!(Delta::::default(), context_margin); + // assert_eq!(grid.margin, margin); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: rich_text_id, + // position: [10., 20.], + // })] + // ); } // #[test] diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index 807b552e81..f1e54e9630 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -240,7 +240,7 @@ impl ContextManager { let pty; #[cfg(not(target_os = "windows"))] { - // if config.use_fork { + if config.use_fork { tracing::info!("rio -> teletypewriter: create_pty_with_fork"); pty = match create_pty_with_fork( &Cow::Borrowed(&config.shell.program), @@ -253,22 +253,22 @@ impl ContextManager { return Err(Box::new(err)); } } - // } else { - // tracing::info!("rio -> teletypewriter: create_pty_with_spawn"); - // pty = match create_pty_with_spawn( - // &Cow::Borrowed(&config.shell.program), - // config.shell.args.clone(), - // &config.working_dir, - // cols, - // rows, - // ) { - // Ok(created_pty) => created_pty, - // Err(err) => { - // tracing::error!("{err:?}"); - // return Err(Box::new(err)); - // } - // } - // }; + } else { + tracing::info!("rio -> teletypewriter: create_pty_with_spawn"); + pty = match create_pty_with_spawn( + &Cow::Borrowed(&config.shell.program), + config.shell.args.clone(), + &config.working_dir, + cols, + rows, + ) { + Ok(created_pty) => created_pty, + Err(err) => { + tracing::error!("{err:?}"); + return Err(Box::new(err)); + } + } + }; } #[cfg(not(target_os = "windows"))] From d4002585c6f19f90d0d1788697c998af3109aac3 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 16:08:48 -0300 Subject: [PATCH 11/20] add mock content --- frontends/rioterm/src/context/grid.rs | 18 +++++++++--------- frontends/rioterm/src/context/mod.rs | 1 + 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index b5535a0214..72fb7fc5c7 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -991,15 +991,15 @@ pub mod test { assert_eq!(context_dimension.columns, 66); assert_eq!(context_dimension.lines, 88); - // let rich_text_id = 1; - // let route_id = 0; - // let context = create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ); + let rich_text_id = 1; + let route_id = 0; + let context = create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ); // let context_width = context.dimension.width; // let context_height = context.dimension.height; // let context_margin = context.dimension.margin; diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index f1e54e9630..51140d25b1 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -197,6 +197,7 @@ pub fn create_mock_context( ); let terminal: Arc>> = Arc::new(FairMutex::new(terminal)); let (sender, _receiver) = corcovado::channel::channel(); + panic!("aaaaa"); Context { route_id, From 76972a0374f42044953504bca192b3eee673c8dd Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 16:36:40 -0300 Subject: [PATCH 12/20] update rich_text_id to 0 and remove panic --- frontends/rioterm/src/context/grid.rs | 2 +- frontends/rioterm/src/context/mod.rs | 8 +- rio-backend/src/config/rio.sublime-workspace | 2416 ++++++++++++++++++ 3 files changed, 2422 insertions(+), 4 deletions(-) create mode 100644 rio-backend/src/config/rio.sublime-workspace diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index 72fb7fc5c7..329c35b516 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -991,7 +991,7 @@ pub mod test { assert_eq!(context_dimension.columns, 66); assert_eq!(context_dimension.lines, 88); - let rich_text_id = 1; + let rich_text_id = 0; let route_id = 0; let context = create_mock_context( VoidListener {}, diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index 51140d25b1..005b4c279a 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -197,7 +197,9 @@ pub fn create_mock_context( ); let terminal: Arc>> = Arc::new(FairMutex::new(terminal)); let (sender, _receiver) = corcovado::channel::channel(); - panic!("aaaaa"); + let messenger = Messenger::new(sender); + let renderable_content = RenderableContent::new(Cursor::default()); + panic!("aaaa"); Context { route_id, @@ -205,8 +207,8 @@ pub fn create_mock_context( main_fd: Arc::new(-1), #[cfg(not(target_os = "windows"))] shell_pid: 1, - messenger: Messenger::new(sender), - renderable_content: RenderableContent::new(Cursor::default()), + messenger, + renderable_content, terminal, rich_text_id, dimension, diff --git a/rio-backend/src/config/rio.sublime-workspace b/rio-backend/src/config/rio.sublime-workspace new file mode 100644 index 0000000000..0cb8c7326b --- /dev/null +++ b/rio-backend/src/config/rio.sublime-workspace @@ -0,0 +1,2416 @@ +{ + "auto_complete": + { + "selected_items": + [ + [ + "Sug", + "SugarCursor" + ], + [ + "line", + "line_height" + ], + [ + "li", + "line_y" + ], + [ + "font_lo", + "fonts_to_load" + ], + [ + "fon", + "font_id" + ], + [ + "pri", + "println\tprintln!(…)" + ], + [ + "cl", + "clone" + ], + [ + "ex", + "extension" + ], + [ + "PRO", + "promoted" + ], + [ + "fo", + "font_id" + ], + [ + "font", + "font_data_extension" + ], + [ + "pr", + "println\tprintln!(…)" + ], + [ + "fonts_", + "fonts_to_load" + ], + [ + "u", + "usize" + ], + [ + "Font", + "FontSource" + ], + [ + "Fo", + "FontData" + ], + [ + "Has", + "HashSet" + ], + [ + "fonts_to", + "fonts_to_load" + ], + [ + "fonts", + "fonts_to_load" + ], + [ + "cle", + "clear" + ], + [ + "to", + "to_owned" + ], + [ + "font_d", + "font_data" + ], + [ + "FontLi", + "FontLibraryDataExtension" + ], + [ + "exe", + "extension_path" + ], + [ + "De", + "Default" + ], + [ + "FontD", + "FontDataLazy" + ], + [ + "dro", + "droppable" + ], + [ + "curr", + "current_font_id" + ], + [ + "font_", + "font_data" + ], + [ + "pa", + "path" + ], + [ + "is", + "is_emoji" + ], + [ + "da", + "data_ref" + ], + [ + "dat", + "data_ref" + ], + [ + "as", + "as_ref" + ], + [ + "by", + "font_by_id" + ], + [ + "fal", + "fallback" + ], + [ + "Pa", + "PathBuf" + ], + [ + "Fontda", + "FontDataLazy" + ], + [ + "to_", + "to_lowercase" + ], + [ + "in", + "into" + ], + [ + "con", + "context" + ], + [ + "scale", + "scale_context" + ], + [ + "Sca", + "ScaleContext" + ], + [ + "sca", + "scale_context" + ], + [ + "sc", + "scaler" + ], + [ + "win", + "window_id" + ], + [ + "wind", + "window_id" + ], + [ + "O", + "Option" + ], + [ + "proce", + "process_open_url" + ], + [ + "use", + "use_wa" + ], + [ + "us", + "use_wa" + ], + [ + "wi", + "window_id" + ], + [ + "rou", + "routes" + ], + [ + "red", + "redraw" + ], + [ + "Mod", + "ModifiersState" + ], + [ + "for", + "format" + ], + [ + "modi", + "modifiers_event" + ], + [ + "mod", + "modifiers" + ], + [ + "Key", + "KeyUp" + ], + [ + "Ke", + "KeyDown" + ], + [ + "Modi", + "Modifiers" + ], + [ + "pal", + "payload" + ], + [ + "po", + "point" + ], + [ + "hi", + "high_dpi" + ], + [ + "di", + "dimensions" + ], + [ + "re", + "return" + ], + [ + "cur", + "current" + ], + [ + "em", + "emoji" + ], + [ + "FON", + "font_data" + ], + [ + "Fon", + "FontData" + ], + [ + "cone", + "clone" + ], + [ + "fot", + "font_id" + ], + [ + "STYL", + "style" + ], + [ + "REG", + "FONT_ID_REGULAR" + ], + [ + "FontRe", + "FontDataRef" + ], + [ + "At", + "AtomicCounter" + ], + [ + "de", + "dead_code" + ] + ] + }, + "buffers": + [ + { + "file": "/Users/rapha/Documents/a/rio/NOTES", + "settings": + { + "buffer_size": 565, + "encoding": "UTF-8", + "line_ending": "Unix" + }, + "undo_stack": + [ + [ + 2, + 1, + "left_delete", + null, + "AQAAAAAAAAAAAAAAAAAAAAAAAADRAAAAIyAwLjEuMAoKLSBMaWdhdHVyYXMgcG9yIGNvbmZpZ3VyYWNhbwotIEFjZXJ0YXIgbyBzZWxlY3Rpb24KLSBBY2VydGFyIGxpbmsgKHVtYSB2ZXogZW5jb250cmFkbyBudW5jYSBtYWlzIG11ZGFyKQotIEZhemVyIHVtIGNhY2hlIHByYSBxdWFuZG8gcm9sYXIgbyBwcmVwYXJlICh0YSBsZXZhbmRvIGFzIHZlemVzIG1ldGFkZSBkbyB0ZW1wbyBwcmEgcmVuZGVyaXphcik", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAAAAAAAAAAANEAAAAAAAAAAAAAAAAA8L8" + ], + [ + 3, + 1, + "insert", + { + "characters": "-" + }, + "AQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8L8" + ], + [ + 4, + 1, + "insert", + { + "characters": " line-" + }, + "BgAAAAEAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAABQAAAAAAAAAAAAAABQAAAAAAAAAGAAAAAAAAAAAAAAAGAAAAAAAAAAcAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAA8L8" + ], + [ + 5, + 1, + "insert", + { + "characters": "gh" + }, + "AgAAAAcAAAAAAAAACAAAAAAAAAAAAAAACAAAAAAAAAAJAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAHAAAAAAAAAAcAAAAAAAAAAAAAAAAA8L8" + ], + [ + 6, + 2, + "left_delete", + null, + "AgAAAAgAAAAAAAAACAAAAAAAAAABAAAAaAcAAAAAAAAABwAAAAAAAAABAAAAZw", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAJAAAAAAAAAAkAAAAAAAAAAAAAAAAA8L8" + ], + [ + 7, + 1, + "insert", + { + "characters": "height" + }, + "BgAAAAcAAAAAAAAACAAAAAAAAAAAAAAACAAAAAAAAAAJAAAAAAAAAAAAAAAJAAAAAAAAAAoAAAAAAAAAAAAAAAoAAAAAAAAACwAAAAAAAAAAAAAACwAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAA0AAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAHAAAAAAAAAAcAAAAAAAAAAAAAAAAA8L8" + ], + [ + 13, + 1, + "insert", + { + "characters": "\n-" + }, + "AgAAAA0AAAAAAAAADgAAAAAAAAAAAAAADgAAAAAAAAAPAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAANAAAAAAAAAA0AAAAAAAAA////////738" + ], + [ + 14, + 1, + "insert", + { + "characters": " consertar" + }, + "CgAAAA8AAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAARAAAAAAAAAAAAAAARAAAAAAAAABIAAAAAAAAAAAAAABIAAAAAAAAAEwAAAAAAAAAAAAAAEwAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAAAAAABUAAAAAAAAAAAAAABUAAAAAAAAAFgAAAAAAAAAAAAAAFgAAAAAAAAAXAAAAAAAAAAAAAAAXAAAAAAAAABgAAAAAAAAAAAAAABgAAAAAAAAAGQAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAPAAAAAAAAAA8AAAAAAAAAAAAAAAAA8L8" + ], + [ + 15, + 1, + "insert", + { + "characters": " bug" + }, + "BAAAABkAAAAAAAAAGgAAAAAAAAAAAAAAGgAAAAAAAAAbAAAAAAAAAAAAAAAbAAAAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAHQAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAZAAAAAAAAABkAAAAAAAAAAAAAAAAA8L8" + ], + [ + 16, + 1, + "insert", + { + "characters": " no" + }, + "AwAAAB0AAAAAAAAAHgAAAAAAAAAAAAAAHgAAAAAAAAAfAAAAAAAAAAAAAAAfAAAAAAAAACAAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAdAAAAAAAAAB0AAAAAAAAAAAAAAAAA8L8" + ], + [ + 17, + 1, + "insert", + { + "characters": " yazi" + }, + "BQAAACAAAAAAAAAAIQAAAAAAAAAAAAAAIQAAAAAAAAAiAAAAAAAAAAAAAAAiAAAAAAAAACMAAAAAAAAAAAAAACMAAAAAAAAAJAAAAAAAAAAAAAAAJAAAAAAAAAAlAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAgAAAAAAAAACAAAAAAAAAAAAAAAAAA8L8" + ], + [ + 18, + 1, + "insert", + { + "characters": "\n-" + }, + "AgAAACUAAAAAAAAAJgAAAAAAAAAAAAAAJgAAAAAAAAAnAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlAAAAAAAAACUAAAAAAAAAAAAAAAAA8L8" + ], + [ + 19, + 1, + "insert", + { + "characters": " ca" + }, + "AwAAACcAAAAAAAAAKAAAAAAAAAAAAAAAKAAAAAAAAAApAAAAAAAAAAAAAAApAAAAAAAAACoAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAnAAAAAAAAACcAAAAAAAAAAAAAAAAA8L8" + ], + [ + 20, + 1, + "left_delete", + null, + "AQAAACkAAAAAAAAAKQAAAAAAAAABAAAAYQ", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAqAAAAAAAAACoAAAAAAAAAAAAAAAAA8L8" + ], + [ + 21, + 1, + "insert", + { + "characters": "haracter" + }, + "CAAAACkAAAAAAAAAKgAAAAAAAAAAAAAAKgAAAAAAAAArAAAAAAAAAAAAAAArAAAAAAAAACwAAAAAAAAAAAAAACwAAAAAAAAALQAAAAAAAAAAAAAALQAAAAAAAAAuAAAAAAAAAAAAAAAuAAAAAAAAAC8AAAAAAAAAAAAAAC8AAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAxAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAApAAAAAAAAACkAAAAAAAAAAAAAAAAA8L8" + ], + [ + 24, + 1, + "paste", + null, + "AgAAACgAAAAAAAAAMgAAAAAAAAAAAAAAMgAAAAAAAAAyAAAAAAAAAAkAAABjaGFyYWN0ZXI", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAxAAAAAAAAACgAAAAAAAAAAAAAAAAA8L8" + ], + [ + 26, + 1, + "insert", + { + "characters": " " + }, + "AQAAADIAAAAAAAAAMwAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAyAAAAAAAAADIAAAAAAAAAAAAAAAAA8L8" + ], + [ + 27, + 1, + "paste", + null, + "AQAAADMAAAAAAAAAXwAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAzAAAAAAAAADMAAAAAAAAAAAAAAAAA8L8" + ], + [ + 29, + 1, + "insert", + { + "characters": "\n\n" + }, + "AgAAAF8AAAAAAAAAYAAAAAAAAAAAAAAAYAAAAAAAAABhAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABfAAAAAAAAAF8AAAAAAAAAAAAAAAAA8L8" + ], + [ + 30, + 1, + "paste", + null, + "AQAAAGEAAAAAAAAAIQIAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABhAAAAAAAAAGEAAAAAAAAAAAAAAAAA8L8" + ], + [ + 33, + 1, + "insert", + { + "characters": "\n\n" + }, + "AgAAAGAAAAAAAAAAYQAAAAAAAAAAAAAAYQAAAAAAAABiAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABgAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAA" + ], + [ + 35, + 1, + "insert", + { + "characters": "Exa" + }, + "AwAAAGEAAAAAAAAAYgAAAAAAAAAAAAAAYgAAAAAAAABjAAAAAAAAAAAAAABjAAAAAAAAAGQAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABhAAAAAAAAAGEAAAAAAAAAAAAAAAAAAAA" + ], + [ + 36, + 1, + "left_delete", + null, + "AQAAAGMAAAAAAAAAYwAAAAAAAAABAAAAYQ", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABkAAAAAAAAAGQAAAAAAAAAAAAAAAAA8L8" + ], + [ + 37, + 1, + "insert", + { + "characters": "emplo" + }, + "BQAAAGMAAAAAAAAAZAAAAAAAAAAAAAAAZAAAAAAAAABlAAAAAAAAAAAAAABlAAAAAAAAAGYAAAAAAAAAAAAAAGYAAAAAAAAAZwAAAAAAAAAAAAAAZwAAAAAAAABoAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABjAAAAAAAAAGMAAAAAAAAAAAAAAAAA8L8" + ], + [ + 38, + 1, + "insert", + { + "characters": " do" + }, + "AwAAAGgAAAAAAAAAaQAAAAAAAAAAAAAAaQAAAAAAAABqAAAAAAAAAAAAAABqAAAAAAAAAGsAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABoAAAAAAAAAGgAAAAAAAAAAAAAAAAA8L8" + ], + [ + 39, + 1, + "insert", + { + "characters": " carlos:" + }, + "CAAAAGsAAAAAAAAAbAAAAAAAAAAAAAAAbAAAAAAAAABtAAAAAAAAAAAAAABtAAAAAAAAAG4AAAAAAAAAAAAAAG4AAAAAAAAAbwAAAAAAAAAAAAAAbwAAAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAHEAAAAAAAAAAAAAAHEAAAAAAAAAcgAAAAAAAAAAAAAAcgAAAAAAAABzAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABrAAAAAAAAAGsAAAAAAAAAAAAAAAAA8L8" + ] + ] + }, + { + "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/mod.rs", + "settings": + { + "buffer_size": 22099, + "line_ending": "Unix" + }, + "undo_stack": + [ + [ + 36, + 1, + "toggle_comment", + { + "block": false + }, + "AQAAANFAAAAAAAAA1EAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADjQAAAAAAAAP1AAAAAAAAAAAAAAAAA8L8" + ], + [ + 42, + 1, + "insert", + { + "characters": "\n" + }, + "AgAAAAFBAAAAAAAAAkEAAAAAAAAAAAAAAkEAAAAAAAAKQQAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAABQQAAAAAAAAFBAAAAAAAAAAAAAAAA8L8" + ], + [ + 43, + 1, + "paste", + null, + "AQAAAApBAAAAAAAAOkEAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAKQQAAAAAAAApBAAAAAAAAAAAAAAAA8L8" + ], + [ + 44, + 1, + "toggle_comment", + { + "block": false + }, + "AQAAAApBAAAAAAAACkEAAAAAAAADAAAALy8g", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAA6QQAAAAAAADpBAAAAAAAAAAAAAAAA8L8" + ], + [ + 47, + 1, + "left_delete", + null, + "AQAAABxBAAAAAAAAHEEAAAAAAAAaAAAAYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAA2QQAAAAAAABxBAAAAAAAAAAAAAAAA8L8" + ], + [ + 48, + 1, + "insert", + { + "characters": "rect.e" + }, + "BgAAABxBAAAAAAAAHUEAAAAAAAAAAAAAHUEAAAAAAAAeQQAAAAAAAAAAAAAeQQAAAAAAAB9BAAAAAAAAAAAAAB9BAAAAAAAAIEEAAAAAAAAAAAAAIEEAAAAAAAAhQQAAAAAAAAAAAAAhQQAAAAAAACJBAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAcQQAAAAAAABxBAAAAAAAAAAAAAAAA8L8" + ], + [ + 49, + 1, + "left_delete", + null, + "AQAAACFBAAAAAAAAIUEAAAAAAAABAAAAZQ", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAiQQAAAAAAACJBAAAAAAAAAAAAAAAA8L8" + ], + [ + 50, + 1, + "insert", + { + "characters": "he" + }, + "AgAAACFBAAAAAAAAIkEAAAAAAAAAAAAAIkEAAAAAAAAjQQAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAhQQAAAAAAACFBAAAAAAAAAAAAAAAA8L8" + ], + [ + 51, + 1, + "insert_completion", + { + "completion": "height", + "format": "text", + "keep_prefix": false, + "must_insert": false, + "trigger": "height" + }, + "AgAAACFBAAAAAAAAIUEAAAAAAAACAAAAaGUhQQAAAAAAACdBAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAjQQAAAAAAACNBAAAAAAAAAAAAAAAA8L8" + ], + [ + 56, + 1, + "toggle_comment", + { + "block": false + }, + "AQAAABVAAAAAAAAAGEAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAtQAAAAAAAAC1AAAAAAAAAAAAAAAAA8L8" + ], + [ + 76, + 1, + "toggle_comment", + { + "block": false + }, + "AQAAAJZAAAAAAAAAmUAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACxQAAAAAAAAKpAAAAAAAAAAAAAAAAA8L8" + ], + [ + 78, + 1, + "insert", + { + "characters": "\nli" + }, + "BAAAALVAAAAAAAAAtkAAAAAAAAAAAAAAtkAAAAAAAAC+QAAAAAAAAAAAAAC+QAAAAAAAAL9AAAAAAAAAAAAAAL9AAAAAAAAAwEAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAC1QAAAAAAAALVAAAAAAAAA////////738" + ], + [ + 84, + 1, + "insert_completion", + { + "completion": "line_y", + "format": "text", + "keep_prefix": false, + "must_insert": false, + "trigger": "line_y" + }, + "AgAAAL5AAAAAAAAAvkAAAAAAAAACAAAAbGm+QAAAAAAAAMRAAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADAQAAAAAAAAMBAAAAAAAAAAAAAAAAA8L8" + ], + [ + 85, + 1, + "insert", + { + "characters": " =" + }, + "AgAAAMRAAAAAAAAAxUAAAAAAAAAAAAAAxUAAAAAAAADGQAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADEQAAAAAAAAMRAAAAAAAAAAAAAAAAA8L8" + ], + [ + 86, + 1, + "insert", + { + "characters": " " + }, + "AQAAAMZAAAAAAAAAx0AAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADGQAAAAAAAAMZAAAAAAAAAAAAAAAAA8L8" + ], + [ + 87, + 1, + "paste", + null, + "AQAAAMdAAAAAAAAA0kAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADHQAAAAAAAAMdAAAAAAAAAAAAAAAAA8L8" + ], + [ + 93, + 1, + "insert", + { + "characters": "l" + }, + "AQAAAMdAAAAAAAAAyEAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADHQAAAAAAAAMdAAAAAAAAAAAAAAAAA8L8" + ], + [ + 94, + 1, + "insert", + { + "characters": " " + }, + "AQAAAMhAAAAAAAAAyUAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADIQAAAAAAAAMhAAAAAAAAAAAAAAAAA8L8" + ], + [ + 96, + 1, + "insert", + { + "characters": "in" + }, + "AgAAAMhAAAAAAAAAyUAAAAAAAAAAAAAAyUAAAAAAAADKQAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADIQAAAAAAAAMhAAAAAAAAAAAAAAAAA8L8" + ], + [ + 97, + 1, + "insert_completion", + { + "completion": "line_y", + "format": "text", + "keep_prefix": false, + "must_insert": false, + "trigger": "line_y" + }, + "AgAAAMdAAAAAAAAAx0AAAAAAAAADAAAAbGlux0AAAAAAAADNQAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADKQAAAAAAAAMpAAAAAAAAAAAAAAAAA8L8" + ], + [ + 98, + 1, + "insert", + { + "characters": " +" + }, + "AgAAAM1AAAAAAAAAzkAAAAAAAAAAAAAAzkAAAAAAAADPQAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADNQAAAAAAAAM1AAAAAAAAAAAAAAAAA8L8" + ], + [ + 100, + 1, + "insert", + { + "characters": ";" + }, + "AQAAANtAAAAAAAAA3EAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADbQAAAAAAAANtAAAAAAAAA////////738" + ], + [ + 102, + 1, + "toggle_comment", + { + "block": false + }, + "AQAAAG5AAAAAAAAAcUAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACMQAAAAAAAAIxAAAAAAAAAAAAAAADAeUA" + ], + [ + 105, + 1, + "toggle_comment", + { + "block": false + }, + "AQAAAOQ/AAAAAAAA5z8AAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAFQAAAAAAAAAVAAAAAAAAAAAAAAADAe0A" + ], + [ + 117, + 1, + "insert", + { + "characters": "rect." + }, + "BgAAAHpEAAAAAAAAe0QAAAAAAAAAAAAAe0QAAAAAAAB7RAAAAAAAAAYAAABhc2NlbnR7RAAAAAAAAHxEAAAAAAAAAAAAAHxEAAAAAAAAfUQAAAAAAAAAAAAAfUQAAAAAAAB+RAAAAAAAAAAAAAB+RAAAAAAAAH9EAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB6RAAAAAAAAIBEAAAAAAAAAAAAAAAA8L8" + ], + [ + 118, + 1, + "insert_completion", + { + "completion": "height", + "format": "text", + "keep_prefix": false, + "must_insert": true, + "trigger": "height" + }, + "AQAAAH9EAAAAAAAAhUQAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB/RAAAAAAAAH9EAAAAAAAAAAAAAAAA8L8" + ], + [ + 121, + 1, + "toggle_comment", + { + "block": false + }, + "AQAAALU/AAAAAAAAuD8AAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADMPwAAAAAAAMw/AAAAAAAAAAAAAAAA8L8" + ], + [ + 124, + 1, + "revert", + null, + "AgAAAAAAAAAAAAAAAAAAAAAAAAC4VgAAbW9kIGJhdGNoOwptb2QgY29tcG9zaXRvcjsKbW9kIGltYWdlX2NhY2hlOwpwdWIgbW9kIHRleHQ7Cgp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OmNvcmU6Om9ydGhvZ3JhcGhpY19wcm9qZWN0aW9uOwp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OnJpY2hfdGV4dDo6aW1hZ2VfY2FjaGU6OntHbHlwaENhY2hlLCBJbWFnZUNhY2hlfTsKdXNlIGNyYXRlOjpjb250ZXh0OjpDb250ZXh0Owp1c2UgY3JhdGU6OmZvbnQ6OkZvbnRMaWJyYXJ5Owp1c2UgY3JhdGU6OmxheW91dDo6U3VnYXJEaW1lbnNpb25zOwp1c2UgY3JhdGU6OnN1Z2FybG9hZjo6Z3JhcGhpY3M6OkdyYXBoaWNSZW5kZXJSZXF1ZXN0Owp1c2UgY3JhdGU6OkdyYXBoaWNzOwp1c2UgY29tcG9zaXRvcjo6e0NvbXBvc2l0b3IsIERpc3BsYXlMaXN0LCBSZWN0LCBWZXJ0ZXh9Owp1c2Ugc3RkOjpjb2xsZWN0aW9uczo6SGFzaFNldDsKdXNlIHN0ZDo6e2JvcnJvdzo6Q293LCBtZW19Owp1c2UgdGV4dDo6e0dseXBoLCBUZXh0UnVuU3R5bGV9Owp1c2Ugd2dwdTo6dXRpbDo6RGV2aWNlRXh0OwoKLy8gTm90ZTogY3VycmVudGx5IGl0J3MgdXNpbmcgSW5kZXhlZCBkcmF3aW5nIGluc3RlYWQgb2YgSW5zdGFuY2UgZHJhd2luZyBjb3VsZCBiZSB3b3J0aCB0bwovLyBldmFsdWF0ZSBpZiB3b3VsZCBtYWtlIHNlbnNlIG1vdmUgdG8gaW5zdGFuY2UgZHJhd2luZyBpbnN0ZWFkCi8vIGh0dHBzOi8vbWF0aC5od3MuZWR1L2dyYXBoaWNzYm9vay9jOS9zMi5odG1sCi8vIGh0dHBzOi8vZG9jcy5ycy93Z3B1L2xhdGVzdC93Z3B1L2VudW0uVmVydGV4U3RlcE1vZGUuaHRtbAoKcHViIGNvbnN0IEJMRU5EOiBPcHRpb248d2dwdTo6QmxlbmRTdGF0ZT4gPSBTb21lKHdncHU6OkJsZW5kU3RhdGUgewogICAgY29sb3I6IHdncHU6OkJsZW5kQ29tcG9uZW50IHsKICAgICAgICBzcmNfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6U3JjQWxwaGEsCiAgICAgICAgZHN0X2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZU1pbnVzU3JjQWxwaGEsCiAgICAgICAgb3BlcmF0aW9uOiB3Z3B1OjpCbGVuZE9wZXJhdGlvbjo6QWRkLAogICAgfSwKICAgIGFscGhhOiB3Z3B1OjpCbGVuZENvbXBvbmVudCB7CiAgICAgICAgc3JjX2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZSwKICAgICAgICBkc3RfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6T25lTWludXNTcmNBbHBoYSwKICAgICAgICBvcGVyYXRpb246IHdncHU6OkJsZW5kT3BlcmF0aW9uOjpBZGQsCiAgICB9LAp9KTsKCnB1YiBzdHJ1Y3QgUmljaFRleHRCcnVzaCB7CiAgICB2ZXJ0ZXhfYnVmZmVyOiB3Z3B1OjpCdWZmZXIsCiAgICBjb25zdGFudF9iaW5kX2dyb3VwOiB3Z3B1OjpCaW5kR3JvdXAsCiAgICBsYXlvdXRfYmluZF9ncm91cDogd2dwdTo6QmluZEdyb3VwLAogICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0OiB3Z3B1OjpCaW5kR3JvdXBMYXlvdXQsCiAgICB0cmFuc2Zvcm06IHdncHU6OkJ1ZmZlciwKICAgIHBpcGVsaW5lOiB3Z3B1OjpSZW5kZXJQaXBlbGluZSwKICAgIGluZGV4X2J1ZmZlcjogd2dwdTo6QnVmZmVyLAogICAgaW5kZXhfYnVmZmVyX3NpemU6IHU2NCwKICAgIGN1cnJlbnRfdHJhbnNmb3JtOiBbZjMyOyAxNl0sCiAgICBjb21wOiBDb21wb3NpdG9yLAogICAgZGxpc3Q6IERpc3BsYXlMaXN0LAogICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXI6IHVzaXplLAogICAgdGV4dHVyZXNfdmVyc2lvbjogdXNpemUsCiAgICBpbWFnZXM6IEltYWdlQ2FjaGUsCiAgICBnbHlwaHM6IEdseXBoQ2FjaGUsCn0KCmltcGwgUmljaFRleHRCcnVzaCB7CiAgICBwdWIgZm4gbmV3KGNvbnRleHQ6ICZDb250ZXh0KSAtPiBTZWxmIHsKICAgICAgICBsZXQgZGV2aWNlID0gJmNvbnRleHQuZGV2aWNlOwogICAgICAgIGxldCBkbGlzdCA9IERpc3BsYXlMaXN0OjpuZXcoKTsKICAgICAgICBsZXQgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIgPSAyXzAwMDsKCiAgICAgICAgbGV0IGN1cnJlbnRfdHJhbnNmb3JtID0KICAgICAgICAgICAgb3J0aG9ncmFwaGljX3Byb2plY3Rpb24oY29udGV4dC5zaXplLndpZHRoLCBjb250ZXh0LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtID0gZGV2aWNlLmNyZWF0ZV9idWZmZXJfaW5pdCgmd2dwdTo6dXRpbDo6QnVmZmVySW5pdERlc2NyaXB0b3IgewogICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgY29udGVudHM6IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZjdXJyZW50X3RyYW5zZm9ybSksCiAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlVOSUZPUk0gfCB3Z3B1OjpCdWZmZXJVc2FnZXM6OkNPUFlfRFNULAogICAgICAgIH0pOwoKICAgICAgICAvLyBDcmVhdGUgcGlwZWxpbmUgbGF5b3V0CiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9iaW5kX2dyb3VwX2xheW91dCgmd2dwdTo6QmluZEdyb3VwTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbCiAgICAgICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwTGF5b3V0RW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmlsaXR5OiB3Z3B1OjpTaGFkZXJTdGFnZXM6OlZFUlRFWCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpCdWZmZXIgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJ1ZmZlckJpbmRpbmdUeXBlOjpVbmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzX2R5bmFtaWNfb2Zmc2V0OiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9iaW5kaW5nX3NpemU6IHdncHU6OkJ1ZmZlclNpemU6Om5ldyhtZW06OnNpemVfb2Y6OjwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZjMyOyAxNl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzIHdncHU6OkJ1ZmZlckFkZHJlc3MpLAogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogTm9uZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgYmluZGluZzogMSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogd2dwdTo6U2hhZGVyU3RhZ2VzOjpWRVJURVgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgd2dwdTo6U2hhZGVyU3RhZ2VzOjpGUkFHTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpTYW1wbGVyKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2dwdTo6U2FtcGxlckJpbmRpbmdUeXBlOjpGaWx0ZXJpbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGxheW91dF9iaW5kX2dyb3VwX2xheW91dCA9CiAgICAgICAgICAgIGRldmljZS5jcmVhdGVfYmluZF9ncm91cF9sYXlvdXQoJndncHU6OkJpbmRHcm91cExheW91dERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgICAgICBlbnRyaWVzOiAmW3dncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6IHdncHU6OlNoYWRlclN0YWdlczo6RlJBR01FTlQsCiAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpUZXh0dXJlIHsKICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX3R5cGU6IHdncHU6OlRleHR1cmVTYW1wbGVUeXBlOjpGbG9hdCB7IGZpbHRlcmFibGU6IHRydWUgfSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlld19kaW1lbnNpb246IHdncHU6OlRleHR1cmVWaWV3RGltZW5zaW9uOjpEMiwKICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlzYW1wbGVkOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgIH0pOwoKICAgICAgICBsZXQgcGlwZWxpbmVfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9waXBlbGluZV9sYXlvdXQoJndncHU6OlBpcGVsaW5lTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIHB1c2hfY29uc3RhbnRfcmFuZ2VzOiAmW10sCiAgICAgICAgICAgICAgICBiaW5kX2dyb3VwX2xheW91dHM6ICZbCiAgICAgICAgICAgICAgICAgICAgJmNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgICZsYXlvdXRfYmluZF9ncm91cF9sYXlvdXQsCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGltYWdlcyA9IEltYWdlQ2FjaGU6Om5ldyhjb250ZXh0KTsKCiAgICAgICAgbGV0IHNhbXBsZXIgPSBkZXZpY2UuY3JlYXRlX3NhbXBsZXIoJndncHU6OlNhbXBsZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3U6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3Y6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3c6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgbWFnX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWluX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWlwbWFwX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbG9kX21pbl9jbGFtcDogMGYzMiwKICAgICAgICAgICAgbG9kX21heF9jbGFtcDogMGYzMiwKICAgICAgICAgICAgLi5EZWZhdWx0OjpkZWZhdWx0KCkKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXAgPSBkZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICBsYXlvdXQ6ICZjb25zdGFudF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlsKICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHJlc291cmNlOiB3Z3B1OjpCaW5kaW5nUmVzb3VyY2U6OkJ1ZmZlcih3Z3B1OjpCdWZmZXJCaW5kaW5nIHsKICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiAmdHJhbnNmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgIGJpbmRpbmc6IDEsCiAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6U2FtcGxlcigmc2FtcGxlciksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICBdLAogICAgICAgICAgICBsYWJlbDogU29tZSgicmljaF90ZXh0Ojpjb25zdGFudF9iaW5kX2dyb3VwIiksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBsYXlvdXRfYmluZF9ncm91cCA9IGRldmljZS5jcmVhdGVfYmluZF9ncm91cCgmd2dwdTo6QmluZEdyb3VwRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxheW91dDogJmxheW91dF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlt3Z3B1OjpCaW5kR3JvdXBFbnRyeSB7CiAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6VGV4dHVyZVZpZXcoJmltYWdlcy50ZXh0dXJlX3ZpZXcpLAogICAgICAgICAgICB9XSwKICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6bGF5b3V0X2JpbmRfZ3JvdXAiKSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHNoYWRlciA9IGRldmljZS5jcmVhdGVfc2hhZGVyX21vZHVsZSh3Z3B1OjpTaGFkZXJNb2R1bGVEZXNjcmlwdG9yIHsKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIHNvdXJjZTogd2dwdTo6U2hhZGVyU291cmNlOjpXZ3NsKENvdzo6Qm9ycm93ZWQoaW5jbHVkZV9zdHIhKAogICAgICAgICAgICAgICAgInJpY2hfdGV4dC53Z3NsIgogICAgICAgICAgICApKSksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBwaXBlbGluZSA9IGRldmljZS5jcmVhdGVfcmVuZGVyX3BpcGVsaW5lKCZ3Z3B1OjpSZW5kZXJQaXBlbGluZURlc2NyaXB0b3IgewogICAgICAgICAgICBjYWNoZTogTm9uZSwKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIGxheW91dDogU29tZSgmcGlwZWxpbmVfbGF5b3V0KSwKICAgICAgICAgICAgdmVydGV4OiB3Z3B1OjpWZXJ0ZXhTdGF0ZSB7CiAgICAgICAgICAgICAgICBjb21waWxhdGlvbl9vcHRpb25zOiB3Z3B1OjpQaXBlbGluZUNvbXBpbGF0aW9uT3B0aW9uczo6ZGVmYXVsdCgpLAogICAgICAgICAgICAgICAgbW9kdWxlOiAmc2hhZGVyLAogICAgICAgICAgICAgICAgZW50cnlfcG9pbnQ6IFNvbWUoInZzX21haW4iKSwKICAgICAgICAgICAgICAgIGJ1ZmZlcnM6ICZbd2dwdTo6VmVydGV4QnVmZmVyTGF5b3V0IHsKICAgICAgICAgICAgICAgICAgICBhcnJheV9zdHJpZGU6IG1lbTo6c2l6ZV9vZjo6PFZlcnRleD4oKSBhcyB1NjQsCiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLnJzL3dncHUvbGF0ZXN0L3dncHUvZW51bS5WZXJ0ZXhTdGVwTW9kZS5odG1sCiAgICAgICAgICAgICAgICAgICAgc3RlcF9tb2RlOiB3Z3B1OjpWZXJ0ZXhTdGVwTW9kZTo6VmVydGV4LAogICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6ICZ3Z3B1Ojp2ZXJ0ZXhfYXR0cl9hcnJheSEoCiAgICAgICAgICAgICAgICAgICAgICAgIDAgPT4gRmxvYXQzMngzLAogICAgICAgICAgICAgICAgICAgICAgICAxID0+IEZsb2F0MzJ4NCwKICAgICAgICAgICAgICAgICAgICAgICAgMiA9PiBGbG9hdDMyeDIsCiAgICAgICAgICAgICAgICAgICAgICAgIDMgPT4gU2ludDMyeDIsCiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIH1dLAogICAgICAgICAgICB9LAogICAgICAgICAgICBmcmFnbWVudDogU29tZSh3Z3B1OjpGcmFnbWVudFN0YXRlIHsKICAgICAgICAgICAgICAgIGNvbXBpbGF0aW9uX29wdGlvbnM6IHdncHU6OlBpcGVsaW5lQ29tcGlsYXRpb25PcHRpb25zOjpkZWZhdWx0KCksCiAgICAgICAgICAgICAgICBtb2R1bGU6ICZzaGFkZXIsCiAgICAgICAgICAgICAgICBlbnRyeV9wb2ludDogU29tZSgiZnNfbWFpbiIpLAogICAgICAgICAgICAgICAgdGFyZ2V0czogJltTb21lKHdncHU6OkNvbG9yVGFyZ2V0U3RhdGUgewogICAgICAgICAgICAgICAgICAgIGZvcm1hdDogY29udGV4dC5mb3JtYXQsCiAgICAgICAgICAgICAgICAgICAgYmxlbmQ6IEJMRU5ELAogICAgICAgICAgICAgICAgICAgIHdyaXRlX21hc2s6IHdncHU6OkNvbG9yV3JpdGVzOjpBTEwsCiAgICAgICAgICAgICAgICB9KV0sCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICBwcmltaXRpdmU6IHdncHU6OlByaW1pdGl2ZVN0YXRlIHsKICAgICAgICAgICAgICAgIHRvcG9sb2d5OiB3Z3B1OjpQcmltaXRpdmVUb3BvbG9neTo6VHJpYW5nbGVMaXN0LAogICAgICAgICAgICAgICAgc3RyaXBfaW5kZXhfZm9ybWF0OiBOb25lLAogICAgICAgICAgICAgICAgZnJvbnRfZmFjZTogd2dwdTo6RnJvbnRGYWNlOjpDY3csCiAgICAgICAgICAgICAgICBjdWxsX21vZGU6IE5vbmUsCiAgICAgICAgICAgICAgICBwb2x5Z29uX21vZGU6IHdncHU6OlBvbHlnb25Nb2RlOjpGaWxsLAogICAgICAgICAgICAgICAgdW5jbGlwcGVkX2RlcHRoOiBmYWxzZSwKICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZTogZmFsc2UsCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGRlcHRoX3N0ZW5jaWw6IE5vbmUsCiAgICAgICAgICAgIG11bHRpc2FtcGxlOiB3Z3B1OjpNdWx0aXNhbXBsZVN0YXRlOjpkZWZhdWx0KCksCiAgICAgICAgICAgIG11bHRpdmlldzogTm9uZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHZlcnRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6Okluc3RhbmNlcyBCdWZmZXIiKSwKICAgICAgICAgICAgc2l6ZTogbWVtOjpzaXplX29mOjo8VmVydGV4PigpIGFzIHU2NCAqIHN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgdXNhZ2U6IHdncHU6OkJ1ZmZlclVzYWdlczo6VkVSVEVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgbWFwcGVkX2F0X2NyZWF0aW9uOiBmYWxzZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplOiAmW3UzMl0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmZGxpc3QuaW5kaWNlcyk7CiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplID0gaW5kZXhfYnVmZmVyX3NpemUubGVuKCkgYXMgdTY0OwogICAgICAgIGxldCBpbmRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6OkluZGljZXMgQnVmZmVyIiksCiAgICAgICAgICAgIHNpemU6IGluZGV4X2J1ZmZlcl9zaXplLAogICAgICAgICAgICB1c2FnZTogd2dwdTo6QnVmZmVyVXNhZ2VzOjpJTkRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogZmFsc2UsCiAgICAgICAgfSk7CgogICAgICAgIFJpY2hUZXh0QnJ1c2ggewogICAgICAgICAgICBsYXlvdXRfYmluZF9ncm91cCwKICAgICAgICAgICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICBjb25zdGFudF9iaW5kX2dyb3VwLAogICAgICAgICAgICBpbmRleF9idWZmZXJfc2l6ZSwKICAgICAgICAgICAgaW5kZXhfYnVmZmVyLAogICAgICAgICAgICBjb21wOiBDb21wb3NpdG9yOjpuZXcoKSwKICAgICAgICAgICAgaW1hZ2VzLAogICAgICAgICAgICB0ZXh0dXJlc192ZXJzaW9uOiAwLAogICAgICAgICAgICBnbHlwaHM6IEdseXBoQ2FjaGU6Om5ldygpLAogICAgICAgICAgICBkbGlzdCwKICAgICAgICAgICAgdHJhbnNmb3JtLAogICAgICAgICAgICBwaXBlbGluZSwKICAgICAgICAgICAgdmVydGV4X2J1ZmZlciwKICAgICAgICAgICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIsCiAgICAgICAgICAgIGN1cnJlbnRfdHJhbnNmb3JtLAogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBwcmVwYXJlKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBjb250ZXh0OiAmbXV0IGNyYXRlOjpjb250ZXh0OjpDb250ZXh0LAogICAgICAgIHN0YXRlOiAmY3JhdGU6OnN1Z2FybG9hZjo6c3RhdGU6OlN1Z2FyU3RhdGUsCiAgICAgICAgZ3JhcGhpY3M6ICZtdXQgR3JhcGhpY3MsCiAgICApIHsKICAgICAgICBpZiBzdGF0ZS5yaWNoX3RleHRzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHNlbGYuY29tcC5iZWdpbigpOwogICAgICAgIGxldCBsaWJyYXJ5ID0gc3RhdGUuY29tcG9zaXRvcnMuYWR2YW5jZWQuZm9udF9saWJyYXJ5KCk7CiAgICAgICAgZm9yIHJpY2hfdGV4dCBpbiAmc3RhdGUucmljaF90ZXh0cyB7CiAgICAgICAgICAgIGlmIGxldCBTb21lKHJ0KSA9IHN0YXRlLmNvbXBvc2l0b3JzLmFkdmFuY2VkLmdldF9yaWNoX3RleHQoJnJpY2hfdGV4dC5pZCkgewogICAgICAgICAgICAgICAgbGV0IHBvc2l0aW9uID0gKAogICAgICAgICAgICAgICAgICAgIHJpY2hfdGV4dC5wb3NpdGlvblswXSAqIHN0YXRlLnN0eWxlLnNjYWxlX2ZhY3RvciwKICAgICAgICAgICAgICAgICAgICByaWNoX3RleHQucG9zaXRpb25bMV0gKiBzdGF0ZS5zdHlsZS5zY2FsZV9mYWN0b3IsCiAgICAgICAgICAgICAgICApOwoKICAgICAgICAgICAgICAgIGRyYXdfbGF5b3V0KAogICAgICAgICAgICAgICAgICAgICZtdXQgc2VsZi5jb21wLAogICAgICAgICAgICAgICAgICAgICgmbXV0IHNlbGYuaW1hZ2VzLCAmbXV0IHNlbGYuZ2x5cGhzKSwKICAgICAgICAgICAgICAgICAgICAmcnQubGluZXMsCiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgICAgICAgICAgbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICAmcnQubGF5b3V0LmRpbWVuc2lvbnMsCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgc2VsZi5pbWFnZXMucHJvY2Vzc19hdGxhc2VzKGNvbnRleHQpOwogICAgICAgIHNlbGYuY29tcC5maW5pc2goJm11dCBzZWxmLmRsaXN0KTsKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBkaW1lbnNpb25zKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgICAgICByZW5kZXJfZGF0YTogJmNyYXRlOjpsYXlvdXQ6OkJ1aWxkZXJMaW5lLAogICAgKSAtPiBPcHRpb248U3VnYXJEaW1lbnNpb25zPiB7CiAgICAgICAgc2VsZi5jb21wLmJlZ2luKCk7CgogICAgICAgIGxldCBkaW1lbnNpb24gPSBmZXRjaF9kaW1lbnNpb25zKAogICAgICAgICAgICAmbXV0IHNlbGYuY29tcCwKICAgICAgICAgICAgKCZtdXQgc2VsZi5pbWFnZXMsICZtdXQgc2VsZi5nbHlwaHMpLAogICAgICAgICAgICByZW5kZXJfZGF0YSwKICAgICAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgICk7CiAgICAgICAgaWYgZGltZW5zaW9uLmhlaWdodCA+IDAuICYmIGRpbWVuc2lvbi53aWR0aCA+IDAuIHsKICAgICAgICAgICAgU29tZShkaW1lbnNpb24pCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgTm9uZQogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiByZXNldCgmbXV0IHNlbGYpIHsKICAgICAgICBzZWxmLmdseXBocyA9IEdseXBoQ2FjaGU6Om5ldygpOwogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHJlbmRlcjwncGFzcz4oCiAgICAgICAgJidwYXNzIG11dCBzZWxmLAogICAgICAgIGN0eDogJm11dCBDb250ZXh0LAogICAgICAgIHJwYXNzOiAmbXV0IHdncHU6OlJlbmRlclBhc3M8J3Bhc3M+LAogICAgKSB7CiAgICAgICAgLy8gbGV0IHN0YXJ0ID0gc3RkOjp0aW1lOjpJbnN0YW50Ojpub3coKTsKICAgICAgICAvLyBUaGVyZSdzIG5vdGhpbmcgdG8gcmVuZGVyCiAgICAgICAgaWYgc2VsZi5kbGlzdC52ZXJ0aWNlcy5pc19lbXB0eSgpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgbGV0IHF1ZXVlID0gJm11dCBjdHgucXVldWU7CgogICAgICAgIGxldCB0cmFuc2Zvcm0gPSBvcnRob2dyYXBoaWNfcHJvamVjdGlvbihjdHguc2l6ZS53aWR0aCwgY3R4LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtX2hhc19jaGFuZ2VkID0gdHJhbnNmb3JtICE9IHNlbGYuY3VycmVudF90cmFuc2Zvcm07CgogICAgICAgIGlmIHRyYW5zZm9ybV9oYXNfY2hhbmdlZCB7CiAgICAgICAgICAgIHF1ZXVlLndyaXRlX2J1ZmZlcigmc2VsZi50cmFuc2Zvcm0sIDAsIGJ5dGVtdWNrOjpieXRlc19vZigmdHJhbnNmb3JtKSk7CiAgICAgICAgICAgIHNlbGYuY3VycmVudF90cmFuc2Zvcm0gPSB0cmFuc2Zvcm07CiAgICAgICAgfQoKICAgICAgICBpZiBzZWxmLmRsaXN0LnZlcnRpY2VzLmxlbigpID4gc2VsZi5zdXBwb3J0ZWRfdmVydGV4X2J1ZmZlciB7CiAgICAgICAgICAgIHNlbGYudmVydGV4X2J1ZmZlci5kZXN0cm95KCk7CgogICAgICAgICAgICBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyID0gc2VsZi5kbGlzdC52ZXJ0aWNlcy5sZW4oKTsKICAgICAgICAgICAgc2VsZi52ZXJ0ZXhfYnVmZmVyID0gY3R4LmRldmljZS5jcmVhdGVfYnVmZmVyKCZ3Z3B1OjpCdWZmZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgICAgIGxhYmVsOiBTb21lKCJzdWdhcmxvYWY6OnJpY2hfdGV4dDo6UGlwZWxpbmUgaW5zdGFuY2VzIiksCiAgICAgICAgICAgICAgICBzaXplOiBtZW06OnNpemVfb2Y6OjxWZXJ0ZXg+KCkgYXMgdTY0CiAgICAgICAgICAgICAgICAgICAgKiBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlZFUlRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgICAgICBtYXBwZWRfYXRfY3JlYXRpb246IGZhbHNlLAogICAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIGxldCB2ZXJ0aWNlc19ieXRlczogJlt1OF0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmc2VsZi5kbGlzdC52ZXJ0aWNlcyk7CiAgICAgICAgaWYgIXZlcnRpY2VzX2J5dGVzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYudmVydGV4X2J1ZmZlciwgMCwgdmVydGljZXNfYnl0ZXMpOwogICAgICAgIH0KCiAgICAgICAgbGV0IGluZGljZXNfcmF3OiAmW3U4XSA9IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZzZWxmLmRsaXN0LmluZGljZXMpOwogICAgICAgIGxldCBpbmRpY2VzX3Jhd19zaXplID0gaW5kaWNlc19yYXcubGVuKCkgYXMgdTY0OwoKICAgICAgICBpZiBzZWxmLmluZGV4X2J1ZmZlcl9zaXplID49IGluZGljZXNfcmF3X3NpemUgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYuaW5kZXhfYnVmZmVyLCAwLCBpbmRpY2VzX3Jhdyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIuZGVzdHJveSgpOwoKICAgICAgICAgICAgbGV0IHNpemUgPSBuZXh0X2NvcHlfYnVmZmVyX3NpemUoaW5kaWNlc19yYXdfc2l6ZSk7CiAgICAgICAgICAgIGxldCBidWZmZXIgPSBjdHguZGV2aWNlLmNyZWF0ZV9idWZmZXIoJndncHU6OkJ1ZmZlckRlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6SW5kaWNlcyIpLAogICAgICAgICAgICAgICAgc2l6ZSwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OklOREVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogdHJ1ZSwKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJ1ZmZlci5zbGljZSguLikuZ2V0X21hcHBlZF9yYW5nZV9tdXQoKVsuLmluZGljZXNfcmF3LmxlbigpXQogICAgICAgICAgICAgICAgLmNvcHlfZnJvbV9zbGljZShpbmRpY2VzX3Jhdyk7CiAgICAgICAgICAgIGJ1ZmZlci51bm1hcCgpOwoKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIgPSBidWZmZXI7CiAgICAgICAgICAgIHNlbGYuaW5kZXhfYnVmZmVyX3NpemUgPSBzaXplOwogICAgICAgIH0KCiAgICAgICAgaWYgc2VsZi50ZXh0dXJlc192ZXJzaW9uICE9IHNlbGYuaW1hZ2VzLmVudHJpZXMubGVuKCkgewogICAgICAgICAgICBzZWxmLnRleHR1cmVzX3ZlcnNpb24gPSBzZWxmLmltYWdlcy5lbnRyaWVzLmxlbigpOwogICAgICAgICAgICBzZWxmLmxheW91dF9iaW5kX2dyb3VwID0KICAgICAgICAgICAgICAgIGN0eC5kZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgICAgIGxheW91dDogJnNlbGYubGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZTogd2dwdTo6QmluZGluZ1Jlc291cmNlOjpUZXh0dXJlVmlldygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICZzZWxmLmltYWdlcy50ZXh0dXJlX3ZpZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6UGlwZWxpbmUgdW5pZm9ybXMiKSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgcnBhc3Muc2V0X3BpcGVsaW5lKCZzZWxmLnBpcGVsaW5lKTsKICAgICAgICBycGFzcy5zZXRfYmluZF9ncm91cCgwLCAmc2VsZi5jb25zdGFudF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF9iaW5kX2dyb3VwKDEsICZzZWxmLmxheW91dF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF92ZXJ0ZXhfYnVmZmVyKDAsIHNlbGYudmVydGV4X2J1ZmZlci5zbGljZSguLikpOwogICAgICAgIHJwYXNzLnNldF9pbmRleF9idWZmZXIoc2VsZi5pbmRleF9idWZmZXIuc2xpY2UoLi4pLCB3Z3B1OjpJbmRleEZvcm1hdDo6VWludDMyKTsKICAgICAgICBycGFzcy5kcmF3X2luZGV4ZWQoMC4uKHNlbGYuZGxpc3QuaW5kaWNlcy5sZW4oKSBhcyB1MzIpLCAwLCAwLi4xKTsKCiAgICAgICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgICAgIC8vIHByaW50bG4hKCIgLSByaWNoX3RleHQ6OnJlbmRlcigpIGlzOiB7Oj99IiwgZHVyYXRpb24pOwogICAgfQp9CgojW2lubGluZV0KZm4gZHJhd19sYXlvdXQoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lczogJlZlYzxjcmF0ZTo6bGF5b3V0OjpCdWlsZGVyTGluZT4sCiAgICBwb3M6IChmMzIsIGYzMiksCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgIHJlY3Q6ICZTdWdhckRpbWVuc2lvbnMsCiAgICBncmFwaGljczogJm11dCBHcmFwaGljcywKKSB7CiAgICAvLyBsZXQgc3RhcnQgPSBzdGQ6OnRpbWU6Okluc3RhbnQ6Om5vdygpOwogICAgbGV0ICh4LCB5KSA9IHBvczsKICAgIGxldCAoaW1hZ2VfY2FjaGUsIGdseXBoc19jYWNoZSkgPSBjYWNoZXM7CiAgICBsZXQgZGVwdGggPSAwLjA7CiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6bmV3KCk7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udCA9IDA7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udF9zaXplID0gMC4wOwogICAgbGV0IGZvbnRfY29vcmRzOiAmW2kxNl0gPSAmWzAsIDAsIDAsIDBdOwogICAgaWYgbGV0IFNvbWUobGluZSkgPSBsaW5lcy5maXJzdCgpIHsKICAgICAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgICAgICBjdXJyZW50X2ZvbnQgPSBmaXJzdF9ydW4uc3Bhbi5mb250X2lkOwogICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IGZpcnN0X3J1bi5zaXplOwogICAgICAgIH0KICAgIH0KCiAgICBnbHlwaHNfY2FjaGUuc2V0X21heF9oZWlnaHQocmVjdC5oZWlnaHQgYXMgdTE2KTsKCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGxhc3RfcmVuZGVyZWRfZ3JhcGhpYyA9IEhhc2hTZXQ6Om5ldygpOwogICAgbGV0IG11dCBsaW5lX3kgPSAwLiArIHk7CiAgICBmb3IgbGluZSBpbiBsaW5lcyB7CiAgICAgICAgaWYgbGluZS5yZW5kZXJfZGF0YS5ydW5zLmlzX2VtcHR5KCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIGxldCBmaXJzdF9ydW4gPSAmbGluZS5yZW5kZXJfZGF0YS5ydW5zWzBdOwogICAgICAgIC8vIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICAgICAgLy8gbGV0IGRlc2NlbnQgPSBmaXJzdF9ydW4uZGVzY2VudC5yb3VuZCgpOwogICAgICAgIC8vIGxldCBsZWFkaW5nID0gKGZpcnN0X3J1bi5sZWFkaW5nKS5yb3VuZCgpICogMi47CiAgICAgICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICAgICAgLy8gbGV0IGJhc2VsaW5lID0gbGluZV95ICsgYXNjZW50OwogICAgICAgIC8vIGxpbmVfeSA9IGJhc2VsaW5lICsgZGVzY2VudDsKICAgICAgICBsaW5lX3kgPSBsaW5lX3kgKyByZWN0LmhlaWdodDsKICAgICAgICBsZXQgcHkgPSBsaW5lX3k7CiAgICAgICAgLy8gbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICAgICAgbGV0IGxpbmVfaGVpZ2h0ID0gcmVjdC5oZWlnaHQ7CiAgICAgICAgZm9yIHJ1biBpbiAmbGluZS5yZW5kZXJfZGF0YS5ydW5zIHsKICAgICAgICAgICAgZ2x5cGhzLmNsZWFyKCk7CiAgICAgICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICAgICAgbGV0IGNoYXJfd2lkdGggPSBydW4uc3Bhbi53aWR0aDsKCiAgICAgICAgICAgIGxldCBydW5feCA9IHB4OwogICAgICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAgICAgbGV0IHggPSBweDsKICAgICAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgICAgICBweCArPSByZWN0LndpZHRoICogY2hhcl93aWR0aDsKICAgICAgICAgICAgICAgIGdseXBocy5wdXNoKEdseXBoIHsKICAgICAgICAgICAgICAgICAgICBpZDogZ2x5cGguc2ltcGxlX2RhdGEoKS4wLAogICAgICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICAgICAgeSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGZvbnRfc2l6ZTogcnVuLnNpemUsCiAgICAgICAgICAgICAgICBjb2xvcjogcnVuLnNwYW4uY29sb3IsCiAgICAgICAgICAgICAgICBjdXJzb3I6IHJ1bi5zcGFuLmN1cnNvciwKICAgICAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IHJ1bi5zcGFuLmJhY2tncm91bmRfY29sb3IsCiAgICAgICAgICAgICAgICBiYXNlbGluZTogcHksCiAgICAgICAgICAgICAgICB0b3BsaW5lOiBweSAtIHJlY3QuaGVpZ2h0LAogICAgICAgICAgICAgICAgbGluZV9oZWlnaHQsCiAgICAgICAgICAgICAgICBhZHZhbmNlOiBweCAtIHJ1bl94LAogICAgICAgICAgICAgICAgZGVjb3JhdGlvbjogcnVuLnNwYW4uZGVjb3JhdGlvbiwKICAgICAgICAgICAgICAgIGRlY29yYXRpb25fY29sb3I6IHJ1bi5zcGFuLmRlY29yYXRpb25fY29sb3IsCiAgICAgICAgICAgIH07CgogICAgICAgICAgICBpZiBmb250ICE9IGN1cnJlbnRfZm9udCB8fCBzdHlsZS5mb250X3NpemUgIT0gY3VycmVudF9mb250X3NpemUgewogICAgICAgICAgICAgICAgY3VycmVudF9mb250ID0gZm9udDsKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplID0gc3R5bGUuZm9udF9zaXplOwoKICAgICAgICAgICAgICAgIHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICAgICAgICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgICAgICAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgICAgICAgICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgICAgICAgICAgICAgIHN0eWxlLmZvbnRfc2l6ZSwKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIGxldCBTb21lKGdyYXBoaWMpID0gcnVuLnNwYW4ubWVkaWEgewogICAgICAgICAgICAgICAgaWYgIWxhc3RfcmVuZGVyZWRfZ3JhcGhpYy5jb250YWlucygmZ3JhcGhpYy5pZCkgewogICAgICAgICAgICAgICAgICAgIGxldCBvZmZzZXRfeCA9IGdyYXBoaWMub2Zmc2V0X3ggYXMgZjMyOwogICAgICAgICAgICAgICAgICAgIGxldCBvZmZzZXRfeSA9IGdyYXBoaWMub2Zmc2V0X3kgYXMgZjMyOwoKICAgICAgICAgICAgICAgICAgICBncmFwaGljcy50b3BfbGF5ZXIucHVzaChHcmFwaGljUmVuZGVyUmVxdWVzdCB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBncmFwaGljLmlkLAogICAgICAgICAgICAgICAgICAgICAgICBwb3NfeDogcnVuX3ggLSBvZmZzZXRfeCwKICAgICAgICAgICAgICAgICAgICAgICAgcG9zX3k6IHN0eWxlLnRvcGxpbmUgLSBvZmZzZXRfeSwKICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogTm9uZSwKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICBsYXN0X3JlbmRlcmVkX2dyYXBoaWMuaW5zZXJ0KGdyYXBoaWMuaWQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICBjb21wLmRyYXdfcnVuKAogICAgICAgICAgICAgICAgJm11dCBzZXNzaW9uLAogICAgICAgICAgICAgICAgUmVjdDo6bmV3KHJ1bl94LCBweSwgc3R5bGUuYWR2YW5jZSwgMS4pLAogICAgICAgICAgICAgICAgZGVwdGgsCiAgICAgICAgICAgICAgICAmc3R5bGUsCiAgICAgICAgICAgICAgICAmZ2x5cGhzLAogICAgICAgICAgICApOwogICAgICAgIH0KICAgIH0KCiAgICAvLyBsZXQgZHVyYXRpb24gPSBzdGFydC5lbGFwc2VkKCk7CiAgICAvLyBwcmludGxuISgiIC0gZHJhd19sYXlvdXQoKSBpczogezo/fVxuIiwgZHVyYXRpb24pOwp9CgojW2lubGluZV0KZm4gZmV0Y2hfZGltZW5zaW9ucygKICAgIGNvbXA6ICZtdXQgY29tcG9zaXRvcjo6Q29tcG9zaXRvciwKICAgIGNhY2hlczogKCZtdXQgSW1hZ2VDYWNoZSwgJm11dCBHbHlwaENhY2hlKSwKICAgIGxpbmU6ICZjcmF0ZTo6bGF5b3V0OjpCdWlsZGVyTGluZSwKICAgIGZvbnRfbGlicmFyeTogJkZvbnRMaWJyYXJ5LAopIC0+IFN1Z2FyRGltZW5zaW9ucyB7CiAgICBsZXQgeCA9IDAuOwogICAgbGV0IHkgPSAwLjsKCiAgICBsZXQgKGltYWdlX2NhY2hlLCBnbHlwaHNfY2FjaGUpID0gY2FjaGVzOwogICAgbGV0IG11dCBjdXJyZW50X2ZvbnQgPSAwOwogICAgbGV0IG11dCBjdXJyZW50X2ZvbnRfc2l6ZSA9IDAuMDsKICAgIGxldCBmb250X2Nvb3JkczogJltpMTZdID0gJlswLCAwLCAwLCAwXTsKICAgIGlmIGxldCBTb21lKGZpcnN0X3J1bikgPSBsaW5lLnJlbmRlcl9kYXRhLnJ1bnMuZmlyc3QoKSB7CiAgICAgICAgY3VycmVudF9mb250ID0gZmlyc3RfcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IGZpcnN0X3J1bi5zaXplOwogICAgfQoKICAgIGxldCBtdXQgc2Vzc2lvbiA9IGdseXBoc19jYWNoZS5zZXNzaW9uKAogICAgICAgIGltYWdlX2NhY2hlLAogICAgICAgIGN1cnJlbnRfZm9udCwKICAgICAgICBmb250X2xpYnJhcnksCiAgICAgICAgZm9udF9jb29yZHMsCiAgICAgICAgY3VycmVudF9mb250X3NpemUsCiAgICApOwoKICAgIGxldCBtdXQgZ2x5cGhzID0gVmVjOjp3aXRoX2NhcGFjaXR5KDMpOwogICAgbGV0IG11dCBkaW1lbnNpb24gPSBTdWdhckRpbWVuc2lvbnM6OmRlZmF1bHQoKTsKICAgIGxldCBmaXJzdF9ydW4gPSAmbGluZS5yZW5kZXJfZGF0YS5ydW5zWzBdOwogICAgbGV0IGFzY2VudCA9IGZpcnN0X3J1bi5hc2NlbnQucm91bmQoKTsKICAgIGxldCBkZXNjZW50ID0gZmlyc3RfcnVuLmRlc2NlbnQucm91bmQoKTsKICAgIGxldCBsZWFkaW5nID0gKGZpcnN0X3J1bi5sZWFkaW5nKS5yb3VuZCgpICogMi47CiAgICAvLyBsZXQgbXV0IHB4ID0geCArIGxpbmUub2Zmc2V0KCk7CiAgICBsZXQgbXV0IHB4ID0geCArIDAuMDsKICAgIGxldCBweSA9IGFzY2VudCArIHk7CiAgICBsZXQgbGluZV9oZWlnaHQgPSBhc2NlbnQgKyBkZXNjZW50ICsgbGVhZGluZzsKICAgIGZvciBydW4gaW4gJmxpbmUucmVuZGVyX2RhdGEucnVucyB7CiAgICAgICAgbGV0IGNoYXJfd2lkdGggPSBydW4uc3Bhbi53aWR0aDsKCiAgICAgICAgbGV0IGZvbnQgPSBydW4uc3Bhbi5mb250X2lkOwogICAgICAgIGxldCBydW5feCA9IHB4OwogICAgICAgIGdseXBocy5jbGVhcigpOwogICAgICAgIGZvciBnbHlwaCBpbiAmcnVuLmdseXBocyB7CiAgICAgICAgICAgIC8vIGxldCB4ID0gcHggKyBnbHlwaC54OwogICAgICAgICAgICAvLyBsZXQgeSA9IHB5IC0gZ2x5cGgueTsKICAgICAgICAgICAgbGV0IHggPSBweDsKICAgICAgICAgICAgbGV0IHkgPSBweTsKICAgICAgICAgICAgLy8gcHggKz0gZ2x5cGguYWR2YW5jZQogICAgICAgICAgICBweCArPSBnbHlwaC5zaW1wbGVfZGF0YSgpLjEgKiBjaGFyX3dpZHRoOwogICAgICAgICAgICBnbHlwaHMucHVzaChHbHlwaCB7CiAgICAgICAgICAgICAgICBpZDogZ2x5cGguc2ltcGxlX2RhdGEoKS4wLAogICAgICAgICAgICAgICAgeCwKICAgICAgICAgICAgICAgIHksCiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBsZXQgY29sb3IgPSBydW4uc3Bhbi5jb2xvcjsKCiAgICAgICAgbGV0IHN0eWxlID0gVGV4dFJ1blN0eWxlIHsKICAgICAgICAgICAgZm9udF9jb29yZHMsCiAgICAgICAgICAgIGZvbnRfc2l6ZTogcnVuLnNpemUsCiAgICAgICAgICAgIGNvbG9yLAogICAgICAgICAgICBjdXJzb3I6IHJ1bi5zcGFuLmN1cnNvciwKICAgICAgICAgICAgYmFja2dyb3VuZF9jb2xvcjogTm9uZSwKICAgICAgICAgICAgYmFzZWxpbmU6IHB5LAogICAgICAgICAgICB0b3BsaW5lOiBweSAtIGFzY2VudCwKICAgICAgICAgICAgbGluZV9oZWlnaHQsCiAgICAgICAgICAgIGFkdmFuY2U6IHB4IC0gcnVuX3gsCiAgICAgICAgICAgIGRlY29yYXRpb246IE5vbmUsCiAgICAgICAgICAgIGRlY29yYXRpb25fY29sb3I6IE5vbmUsCiAgICAgICAgfTsKCiAgICAgICAgaWYgc3R5bGUuYWR2YW5jZSA+IDAuICYmIGxpbmVfaGVpZ2h0ID4gMC4gewogICAgICAgICAgICBkaW1lbnNpb24ud2lkdGggPSBzdHlsZS5hZHZhbmNlLnJvdW5kKCk7CiAgICAgICAgICAgIGRpbWVuc2lvbi5oZWlnaHQgPSBsaW5lX2hlaWdodC5yb3VuZCgpOwogICAgICAgIH0KCiAgICAgICAgaWYgZm9udCAhPSBjdXJyZW50X2ZvbnQgfHwgc3R5bGUuZm9udF9zaXplICE9IGN1cnJlbnRfZm9udF9zaXplIHsKICAgICAgICAgICAgY3VycmVudF9mb250ID0gZm9udDsKICAgICAgICAgICAgY3VycmVudF9mb250X3NpemUgPSBzdHlsZS5mb250X3NpemU7CgogICAgICAgICAgICBzZXNzaW9uID0gZ2x5cGhzX2NhY2hlLnNlc3Npb24oCiAgICAgICAgICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udCwKICAgICAgICAgICAgICAgIGZvbnRfbGlicmFyeSwKICAgICAgICAgICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgICAgICAgICAgY3VycmVudF9mb250X3NpemUsCiAgICAgICAgICAgICk7CiAgICAgICAgfQoKICAgICAgICBjb21wLmRyYXdfcnVuKAogICAgICAgICAgICAmbXV0IHNlc3Npb24sCiAgICAgICAgICAgIFJlY3Q6Om5ldyhydW5feCwgcHksIHN0eWxlLmFkdmFuY2UsIDEuKSwKICAgICAgICAgICAgMC4wLAogICAgICAgICAgICAmc3R5bGUsCiAgICAgICAgICAgICZnbHlwaHMsCiAgICAgICAgKTsKICAgIH0KCiAgICBkaW1lbnNpb24KfQoKI1tpbmxpbmVdCmZuIG5leHRfY29weV9idWZmZXJfc2l6ZShzaXplOiB1NjQpIC0+IHU2NCB7CiAgICBsZXQgYWxpZ25fbWFzayA9IHdncHU6OkNPUFlfQlVGRkVSX0FMSUdOTUVOVCAtIDE7CiAgICAoKHNpemUubmV4dF9wb3dlcl9vZl90d28oKSArIGFsaWduX21hc2spICYgIWFsaWduX21hc2spCiAgICAgICAgLm1heCh3Z3B1OjpDT1BZX0JVRkZFUl9BTElHTk1FTlQpCn0KAAAAAAAAAABTVgAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACZPwAAAAAAAJk/AAAAAAAAAAAAAAAA8L8" + ], + [ + 125, + 1, + "revert", + null, + "AgAAAAAAAAAAAAAAAAAAAAAAAABTVgAAbW9kIGJhdGNoOwptb2QgY29tcG9zaXRvcjsKbW9kIGltYWdlX2NhY2hlOwpwdWIgbW9kIHRleHQ7Cgp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OmNvcmU6Om9ydGhvZ3JhcGhpY19wcm9qZWN0aW9uOwp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OnJpY2hfdGV4dDo6aW1hZ2VfY2FjaGU6OntHbHlwaENhY2hlLCBJbWFnZUNhY2hlfTsKdXNlIGNyYXRlOjpjb250ZXh0OjpDb250ZXh0Owp1c2UgY3JhdGU6OmZvbnQ6OkZvbnRMaWJyYXJ5Owp1c2UgY3JhdGU6OmxheW91dDo6U3VnYXJEaW1lbnNpb25zOwp1c2UgY3JhdGU6OnN1Z2FybG9hZjo6Z3JhcGhpY3M6OkdyYXBoaWNSZW5kZXJSZXF1ZXN0Owp1c2UgY3JhdGU6OkdyYXBoaWNzOwp1c2UgY29tcG9zaXRvcjo6e0NvbXBvc2l0b3IsIERpc3BsYXlMaXN0LCBSZWN0LCBWZXJ0ZXh9Owp1c2Ugc3RkOjpjb2xsZWN0aW9uczo6SGFzaFNldDsKdXNlIHN0ZDo6e2JvcnJvdzo6Q293LCBtZW19Owp1c2UgdGV4dDo6e0dseXBoLCBUZXh0UnVuU3R5bGV9Owp1c2Ugd2dwdTo6dXRpbDo6RGV2aWNlRXh0OwoKLy8gTm90ZTogY3VycmVudGx5IGl0J3MgdXNpbmcgSW5kZXhlZCBkcmF3aW5nIGluc3RlYWQgb2YgSW5zdGFuY2UgZHJhd2luZyBjb3VsZCBiZSB3b3J0aCB0bwovLyBldmFsdWF0ZSBpZiB3b3VsZCBtYWtlIHNlbnNlIG1vdmUgdG8gaW5zdGFuY2UgZHJhd2luZyBpbnN0ZWFkCi8vIGh0dHBzOi8vbWF0aC5od3MuZWR1L2dyYXBoaWNzYm9vay9jOS9zMi5odG1sCi8vIGh0dHBzOi8vZG9jcy5ycy93Z3B1L2xhdGVzdC93Z3B1L2VudW0uVmVydGV4U3RlcE1vZGUuaHRtbAoKcHViIGNvbnN0IEJMRU5EOiBPcHRpb248d2dwdTo6QmxlbmRTdGF0ZT4gPSBTb21lKHdncHU6OkJsZW5kU3RhdGUgewogICAgY29sb3I6IHdncHU6OkJsZW5kQ29tcG9uZW50IHsKICAgICAgICBzcmNfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6U3JjQWxwaGEsCiAgICAgICAgZHN0X2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZU1pbnVzU3JjQWxwaGEsCiAgICAgICAgb3BlcmF0aW9uOiB3Z3B1OjpCbGVuZE9wZXJhdGlvbjo6QWRkLAogICAgfSwKICAgIGFscGhhOiB3Z3B1OjpCbGVuZENvbXBvbmVudCB7CiAgICAgICAgc3JjX2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZSwKICAgICAgICBkc3RfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6T25lTWludXNTcmNBbHBoYSwKICAgICAgICBvcGVyYXRpb246IHdncHU6OkJsZW5kT3BlcmF0aW9uOjpBZGQsCiAgICB9LAp9KTsKCnB1YiBzdHJ1Y3QgUmljaFRleHRCcnVzaCB7CiAgICB2ZXJ0ZXhfYnVmZmVyOiB3Z3B1OjpCdWZmZXIsCiAgICBjb25zdGFudF9iaW5kX2dyb3VwOiB3Z3B1OjpCaW5kR3JvdXAsCiAgICBsYXlvdXRfYmluZF9ncm91cDogd2dwdTo6QmluZEdyb3VwLAogICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0OiB3Z3B1OjpCaW5kR3JvdXBMYXlvdXQsCiAgICB0cmFuc2Zvcm06IHdncHU6OkJ1ZmZlciwKICAgIHBpcGVsaW5lOiB3Z3B1OjpSZW5kZXJQaXBlbGluZSwKICAgIGluZGV4X2J1ZmZlcjogd2dwdTo6QnVmZmVyLAogICAgaW5kZXhfYnVmZmVyX3NpemU6IHU2NCwKICAgIGN1cnJlbnRfdHJhbnNmb3JtOiBbZjMyOyAxNl0sCiAgICBjb21wOiBDb21wb3NpdG9yLAogICAgZGxpc3Q6IERpc3BsYXlMaXN0LAogICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXI6IHVzaXplLAogICAgdGV4dHVyZXNfdmVyc2lvbjogdXNpemUsCiAgICBpbWFnZXM6IEltYWdlQ2FjaGUsCiAgICBnbHlwaHM6IEdseXBoQ2FjaGUsCn0KCmltcGwgUmljaFRleHRCcnVzaCB7CiAgICBwdWIgZm4gbmV3KGNvbnRleHQ6ICZDb250ZXh0KSAtPiBTZWxmIHsKICAgICAgICBsZXQgZGV2aWNlID0gJmNvbnRleHQuZGV2aWNlOwogICAgICAgIGxldCBkbGlzdCA9IERpc3BsYXlMaXN0OjpuZXcoKTsKICAgICAgICBsZXQgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIgPSAyXzAwMDsKCiAgICAgICAgbGV0IGN1cnJlbnRfdHJhbnNmb3JtID0KICAgICAgICAgICAgb3J0aG9ncmFwaGljX3Byb2plY3Rpb24oY29udGV4dC5zaXplLndpZHRoLCBjb250ZXh0LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtID0gZGV2aWNlLmNyZWF0ZV9idWZmZXJfaW5pdCgmd2dwdTo6dXRpbDo6QnVmZmVySW5pdERlc2NyaXB0b3IgewogICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgY29udGVudHM6IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZjdXJyZW50X3RyYW5zZm9ybSksCiAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlVOSUZPUk0gfCB3Z3B1OjpCdWZmZXJVc2FnZXM6OkNPUFlfRFNULAogICAgICAgIH0pOwoKICAgICAgICAvLyBDcmVhdGUgcGlwZWxpbmUgbGF5b3V0CiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9iaW5kX2dyb3VwX2xheW91dCgmd2dwdTo6QmluZEdyb3VwTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbCiAgICAgICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwTGF5b3V0RW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmlsaXR5OiB3Z3B1OjpTaGFkZXJTdGFnZXM6OlZFUlRFWCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpCdWZmZXIgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJ1ZmZlckJpbmRpbmdUeXBlOjpVbmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzX2R5bmFtaWNfb2Zmc2V0OiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9iaW5kaW5nX3NpemU6IHdncHU6OkJ1ZmZlclNpemU6Om5ldyhtZW06OnNpemVfb2Y6OjwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZjMyOyAxNl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzIHdncHU6OkJ1ZmZlckFkZHJlc3MpLAogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogTm9uZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgYmluZGluZzogMSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogd2dwdTo6U2hhZGVyU3RhZ2VzOjpWRVJURVgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgd2dwdTo6U2hhZGVyU3RhZ2VzOjpGUkFHTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpTYW1wbGVyKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2dwdTo6U2FtcGxlckJpbmRpbmdUeXBlOjpGaWx0ZXJpbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGxheW91dF9iaW5kX2dyb3VwX2xheW91dCA9CiAgICAgICAgICAgIGRldmljZS5jcmVhdGVfYmluZF9ncm91cF9sYXlvdXQoJndncHU6OkJpbmRHcm91cExheW91dERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgICAgICBlbnRyaWVzOiAmW3dncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6IHdncHU6OlNoYWRlclN0YWdlczo6RlJBR01FTlQsCiAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpUZXh0dXJlIHsKICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX3R5cGU6IHdncHU6OlRleHR1cmVTYW1wbGVUeXBlOjpGbG9hdCB7IGZpbHRlcmFibGU6IHRydWUgfSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlld19kaW1lbnNpb246IHdncHU6OlRleHR1cmVWaWV3RGltZW5zaW9uOjpEMiwKICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlzYW1wbGVkOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgIH0pOwoKICAgICAgICBsZXQgcGlwZWxpbmVfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9waXBlbGluZV9sYXlvdXQoJndncHU6OlBpcGVsaW5lTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIHB1c2hfY29uc3RhbnRfcmFuZ2VzOiAmW10sCiAgICAgICAgICAgICAgICBiaW5kX2dyb3VwX2xheW91dHM6ICZbCiAgICAgICAgICAgICAgICAgICAgJmNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgICZsYXlvdXRfYmluZF9ncm91cF9sYXlvdXQsCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGltYWdlcyA9IEltYWdlQ2FjaGU6Om5ldyhjb250ZXh0KTsKCiAgICAgICAgbGV0IHNhbXBsZXIgPSBkZXZpY2UuY3JlYXRlX3NhbXBsZXIoJndncHU6OlNhbXBsZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3U6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3Y6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3c6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgbWFnX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWluX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWlwbWFwX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbG9kX21pbl9jbGFtcDogMGYzMiwKICAgICAgICAgICAgbG9kX21heF9jbGFtcDogMGYzMiwKICAgICAgICAgICAgLi5EZWZhdWx0OjpkZWZhdWx0KCkKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXAgPSBkZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICBsYXlvdXQ6ICZjb25zdGFudF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlsKICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHJlc291cmNlOiB3Z3B1OjpCaW5kaW5nUmVzb3VyY2U6OkJ1ZmZlcih3Z3B1OjpCdWZmZXJCaW5kaW5nIHsKICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiAmdHJhbnNmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgIGJpbmRpbmc6IDEsCiAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6U2FtcGxlcigmc2FtcGxlciksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICBdLAogICAgICAgICAgICBsYWJlbDogU29tZSgicmljaF90ZXh0Ojpjb25zdGFudF9iaW5kX2dyb3VwIiksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBsYXlvdXRfYmluZF9ncm91cCA9IGRldmljZS5jcmVhdGVfYmluZF9ncm91cCgmd2dwdTo6QmluZEdyb3VwRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxheW91dDogJmxheW91dF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlt3Z3B1OjpCaW5kR3JvdXBFbnRyeSB7CiAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6VGV4dHVyZVZpZXcoJmltYWdlcy50ZXh0dXJlX3ZpZXcpLAogICAgICAgICAgICB9XSwKICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6bGF5b3V0X2JpbmRfZ3JvdXAiKSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHNoYWRlciA9IGRldmljZS5jcmVhdGVfc2hhZGVyX21vZHVsZSh3Z3B1OjpTaGFkZXJNb2R1bGVEZXNjcmlwdG9yIHsKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIHNvdXJjZTogd2dwdTo6U2hhZGVyU291cmNlOjpXZ3NsKENvdzo6Qm9ycm93ZWQoaW5jbHVkZV9zdHIhKAogICAgICAgICAgICAgICAgInJpY2hfdGV4dC53Z3NsIgogICAgICAgICAgICApKSksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBwaXBlbGluZSA9IGRldmljZS5jcmVhdGVfcmVuZGVyX3BpcGVsaW5lKCZ3Z3B1OjpSZW5kZXJQaXBlbGluZURlc2NyaXB0b3IgewogICAgICAgICAgICBjYWNoZTogTm9uZSwKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIGxheW91dDogU29tZSgmcGlwZWxpbmVfbGF5b3V0KSwKICAgICAgICAgICAgdmVydGV4OiB3Z3B1OjpWZXJ0ZXhTdGF0ZSB7CiAgICAgICAgICAgICAgICBjb21waWxhdGlvbl9vcHRpb25zOiB3Z3B1OjpQaXBlbGluZUNvbXBpbGF0aW9uT3B0aW9uczo6ZGVmYXVsdCgpLAogICAgICAgICAgICAgICAgbW9kdWxlOiAmc2hhZGVyLAogICAgICAgICAgICAgICAgZW50cnlfcG9pbnQ6IFNvbWUoInZzX21haW4iKSwKICAgICAgICAgICAgICAgIGJ1ZmZlcnM6ICZbd2dwdTo6VmVydGV4QnVmZmVyTGF5b3V0IHsKICAgICAgICAgICAgICAgICAgICBhcnJheV9zdHJpZGU6IG1lbTo6c2l6ZV9vZjo6PFZlcnRleD4oKSBhcyB1NjQsCiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLnJzL3dncHUvbGF0ZXN0L3dncHUvZW51bS5WZXJ0ZXhTdGVwTW9kZS5odG1sCiAgICAgICAgICAgICAgICAgICAgc3RlcF9tb2RlOiB3Z3B1OjpWZXJ0ZXhTdGVwTW9kZTo6VmVydGV4LAogICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6ICZ3Z3B1Ojp2ZXJ0ZXhfYXR0cl9hcnJheSEoCiAgICAgICAgICAgICAgICAgICAgICAgIDAgPT4gRmxvYXQzMngzLAogICAgICAgICAgICAgICAgICAgICAgICAxID0+IEZsb2F0MzJ4NCwKICAgICAgICAgICAgICAgICAgICAgICAgMiA9PiBGbG9hdDMyeDIsCiAgICAgICAgICAgICAgICAgICAgICAgIDMgPT4gU2ludDMyeDIsCiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIH1dLAogICAgICAgICAgICB9LAogICAgICAgICAgICBmcmFnbWVudDogU29tZSh3Z3B1OjpGcmFnbWVudFN0YXRlIHsKICAgICAgICAgICAgICAgIGNvbXBpbGF0aW9uX29wdGlvbnM6IHdncHU6OlBpcGVsaW5lQ29tcGlsYXRpb25PcHRpb25zOjpkZWZhdWx0KCksCiAgICAgICAgICAgICAgICBtb2R1bGU6ICZzaGFkZXIsCiAgICAgICAgICAgICAgICBlbnRyeV9wb2ludDogU29tZSgiZnNfbWFpbiIpLAogICAgICAgICAgICAgICAgdGFyZ2V0czogJltTb21lKHdncHU6OkNvbG9yVGFyZ2V0U3RhdGUgewogICAgICAgICAgICAgICAgICAgIGZvcm1hdDogY29udGV4dC5mb3JtYXQsCiAgICAgICAgICAgICAgICAgICAgYmxlbmQ6IEJMRU5ELAogICAgICAgICAgICAgICAgICAgIHdyaXRlX21hc2s6IHdncHU6OkNvbG9yV3JpdGVzOjpBTEwsCiAgICAgICAgICAgICAgICB9KV0sCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICBwcmltaXRpdmU6IHdncHU6OlByaW1pdGl2ZVN0YXRlIHsKICAgICAgICAgICAgICAgIHRvcG9sb2d5OiB3Z3B1OjpQcmltaXRpdmVUb3BvbG9neTo6VHJpYW5nbGVMaXN0LAogICAgICAgICAgICAgICAgc3RyaXBfaW5kZXhfZm9ybWF0OiBOb25lLAogICAgICAgICAgICAgICAgZnJvbnRfZmFjZTogd2dwdTo6RnJvbnRGYWNlOjpDY3csCiAgICAgICAgICAgICAgICBjdWxsX21vZGU6IE5vbmUsCiAgICAgICAgICAgICAgICBwb2x5Z29uX21vZGU6IHdncHU6OlBvbHlnb25Nb2RlOjpGaWxsLAogICAgICAgICAgICAgICAgdW5jbGlwcGVkX2RlcHRoOiBmYWxzZSwKICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZTogZmFsc2UsCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGRlcHRoX3N0ZW5jaWw6IE5vbmUsCiAgICAgICAgICAgIG11bHRpc2FtcGxlOiB3Z3B1OjpNdWx0aXNhbXBsZVN0YXRlOjpkZWZhdWx0KCksCiAgICAgICAgICAgIG11bHRpdmlldzogTm9uZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHZlcnRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6Okluc3RhbmNlcyBCdWZmZXIiKSwKICAgICAgICAgICAgc2l6ZTogbWVtOjpzaXplX29mOjo8VmVydGV4PigpIGFzIHU2NCAqIHN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgdXNhZ2U6IHdncHU6OkJ1ZmZlclVzYWdlczo6VkVSVEVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgbWFwcGVkX2F0X2NyZWF0aW9uOiBmYWxzZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplOiAmW3UzMl0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmZGxpc3QuaW5kaWNlcyk7CiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplID0gaW5kZXhfYnVmZmVyX3NpemUubGVuKCkgYXMgdTY0OwogICAgICAgIGxldCBpbmRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6OkluZGljZXMgQnVmZmVyIiksCiAgICAgICAgICAgIHNpemU6IGluZGV4X2J1ZmZlcl9zaXplLAogICAgICAgICAgICB1c2FnZTogd2dwdTo6QnVmZmVyVXNhZ2VzOjpJTkRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogZmFsc2UsCiAgICAgICAgfSk7CgogICAgICAgIFJpY2hUZXh0QnJ1c2ggewogICAgICAgICAgICBsYXlvdXRfYmluZF9ncm91cCwKICAgICAgICAgICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICBjb25zdGFudF9iaW5kX2dyb3VwLAogICAgICAgICAgICBpbmRleF9idWZmZXJfc2l6ZSwKICAgICAgICAgICAgaW5kZXhfYnVmZmVyLAogICAgICAgICAgICBjb21wOiBDb21wb3NpdG9yOjpuZXcoKSwKICAgICAgICAgICAgaW1hZ2VzLAogICAgICAgICAgICB0ZXh0dXJlc192ZXJzaW9uOiAwLAogICAgICAgICAgICBnbHlwaHM6IEdseXBoQ2FjaGU6Om5ldygpLAogICAgICAgICAgICBkbGlzdCwKICAgICAgICAgICAgdHJhbnNmb3JtLAogICAgICAgICAgICBwaXBlbGluZSwKICAgICAgICAgICAgdmVydGV4X2J1ZmZlciwKICAgICAgICAgICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIsCiAgICAgICAgICAgIGN1cnJlbnRfdHJhbnNmb3JtLAogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBwcmVwYXJlKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBjb250ZXh0OiAmbXV0IGNyYXRlOjpjb250ZXh0OjpDb250ZXh0LAogICAgICAgIHN0YXRlOiAmY3JhdGU6OnN1Z2FybG9hZjo6c3RhdGU6OlN1Z2FyU3RhdGUsCiAgICAgICAgZ3JhcGhpY3M6ICZtdXQgR3JhcGhpY3MsCiAgICApIHsKICAgICAgICBpZiBzdGF0ZS5yaWNoX3RleHRzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHNlbGYuY29tcC5iZWdpbigpOwogICAgICAgIGxldCBsaWJyYXJ5ID0gc3RhdGUuY29tcG9zaXRvcnMuYWR2YW5jZWQuZm9udF9saWJyYXJ5KCk7CiAgICAgICAgZm9yIHJpY2hfdGV4dCBpbiAmc3RhdGUucmljaF90ZXh0cyB7CiAgICAgICAgICAgIGlmIGxldCBTb21lKHJ0KSA9IHN0YXRlLmNvbXBvc2l0b3JzLmFkdmFuY2VkLmdldF9yaWNoX3RleHQoJnJpY2hfdGV4dC5pZCkgewogICAgICAgICAgICAgICAgbGV0IHBvc2l0aW9uID0gKAogICAgICAgICAgICAgICAgICAgIHJpY2hfdGV4dC5wb3NpdGlvblswXSAqIHN0YXRlLnN0eWxlLnNjYWxlX2ZhY3RvciwKICAgICAgICAgICAgICAgICAgICByaWNoX3RleHQucG9zaXRpb25bMV0gKiBzdGF0ZS5zdHlsZS5zY2FsZV9mYWN0b3IsCiAgICAgICAgICAgICAgICApOwoKICAgICAgICAgICAgICAgIGRyYXdfbGF5b3V0KAogICAgICAgICAgICAgICAgICAgICZtdXQgc2VsZi5jb21wLAogICAgICAgICAgICAgICAgICAgICgmbXV0IHNlbGYuaW1hZ2VzLCAmbXV0IHNlbGYuZ2x5cGhzKSwKICAgICAgICAgICAgICAgICAgICAmcnQubGluZXMsCiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgICAgICAgICAgbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICAmcnQubGF5b3V0LmRpbWVuc2lvbnMsCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgc2VsZi5pbWFnZXMucHJvY2Vzc19hdGxhc2VzKGNvbnRleHQpOwogICAgICAgIHNlbGYuY29tcC5maW5pc2goJm11dCBzZWxmLmRsaXN0KTsKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBkaW1lbnNpb25zKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgICAgICByZW5kZXJfZGF0YTogJmNyYXRlOjpsYXlvdXQ6OkJ1aWxkZXJMaW5lLAogICAgKSAtPiBPcHRpb248U3VnYXJEaW1lbnNpb25zPiB7CiAgICAgICAgc2VsZi5jb21wLmJlZ2luKCk7CgogICAgICAgIGxldCBkaW1lbnNpb24gPSBmZXRjaF9kaW1lbnNpb25zKAogICAgICAgICAgICAmbXV0IHNlbGYuY29tcCwKICAgICAgICAgICAgKCZtdXQgc2VsZi5pbWFnZXMsICZtdXQgc2VsZi5nbHlwaHMpLAogICAgICAgICAgICByZW5kZXJfZGF0YSwKICAgICAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgICk7CiAgICAgICAgaWYgZGltZW5zaW9uLmhlaWdodCA+IDAuICYmIGRpbWVuc2lvbi53aWR0aCA+IDAuIHsKICAgICAgICAgICAgU29tZShkaW1lbnNpb24pCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgTm9uZQogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiByZXNldCgmbXV0IHNlbGYpIHsKICAgICAgICBzZWxmLmdseXBocyA9IEdseXBoQ2FjaGU6Om5ldygpOwogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHJlbmRlcjwncGFzcz4oCiAgICAgICAgJidwYXNzIG11dCBzZWxmLAogICAgICAgIGN0eDogJm11dCBDb250ZXh0LAogICAgICAgIHJwYXNzOiAmbXV0IHdncHU6OlJlbmRlclBhc3M8J3Bhc3M+LAogICAgKSB7CiAgICAgICAgLy8gbGV0IHN0YXJ0ID0gc3RkOjp0aW1lOjpJbnN0YW50Ojpub3coKTsKICAgICAgICAvLyBUaGVyZSdzIG5vdGhpbmcgdG8gcmVuZGVyCiAgICAgICAgaWYgc2VsZi5kbGlzdC52ZXJ0aWNlcy5pc19lbXB0eSgpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgbGV0IHF1ZXVlID0gJm11dCBjdHgucXVldWU7CgogICAgICAgIGxldCB0cmFuc2Zvcm0gPSBvcnRob2dyYXBoaWNfcHJvamVjdGlvbihjdHguc2l6ZS53aWR0aCwgY3R4LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtX2hhc19jaGFuZ2VkID0gdHJhbnNmb3JtICE9IHNlbGYuY3VycmVudF90cmFuc2Zvcm07CgogICAgICAgIGlmIHRyYW5zZm9ybV9oYXNfY2hhbmdlZCB7CiAgICAgICAgICAgIHF1ZXVlLndyaXRlX2J1ZmZlcigmc2VsZi50cmFuc2Zvcm0sIDAsIGJ5dGVtdWNrOjpieXRlc19vZigmdHJhbnNmb3JtKSk7CiAgICAgICAgICAgIHNlbGYuY3VycmVudF90cmFuc2Zvcm0gPSB0cmFuc2Zvcm07CiAgICAgICAgfQoKICAgICAgICBpZiBzZWxmLmRsaXN0LnZlcnRpY2VzLmxlbigpID4gc2VsZi5zdXBwb3J0ZWRfdmVydGV4X2J1ZmZlciB7CiAgICAgICAgICAgIHNlbGYudmVydGV4X2J1ZmZlci5kZXN0cm95KCk7CgogICAgICAgICAgICBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyID0gc2VsZi5kbGlzdC52ZXJ0aWNlcy5sZW4oKTsKICAgICAgICAgICAgc2VsZi52ZXJ0ZXhfYnVmZmVyID0gY3R4LmRldmljZS5jcmVhdGVfYnVmZmVyKCZ3Z3B1OjpCdWZmZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgICAgIGxhYmVsOiBTb21lKCJzdWdhcmxvYWY6OnJpY2hfdGV4dDo6UGlwZWxpbmUgaW5zdGFuY2VzIiksCiAgICAgICAgICAgICAgICBzaXplOiBtZW06OnNpemVfb2Y6OjxWZXJ0ZXg+KCkgYXMgdTY0CiAgICAgICAgICAgICAgICAgICAgKiBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlZFUlRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgICAgICBtYXBwZWRfYXRfY3JlYXRpb246IGZhbHNlLAogICAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIGxldCB2ZXJ0aWNlc19ieXRlczogJlt1OF0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmc2VsZi5kbGlzdC52ZXJ0aWNlcyk7CiAgICAgICAgaWYgIXZlcnRpY2VzX2J5dGVzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYudmVydGV4X2J1ZmZlciwgMCwgdmVydGljZXNfYnl0ZXMpOwogICAgICAgIH0KCiAgICAgICAgbGV0IGluZGljZXNfcmF3OiAmW3U4XSA9IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZzZWxmLmRsaXN0LmluZGljZXMpOwogICAgICAgIGxldCBpbmRpY2VzX3Jhd19zaXplID0gaW5kaWNlc19yYXcubGVuKCkgYXMgdTY0OwoKICAgICAgICBpZiBzZWxmLmluZGV4X2J1ZmZlcl9zaXplID49IGluZGljZXNfcmF3X3NpemUgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYuaW5kZXhfYnVmZmVyLCAwLCBpbmRpY2VzX3Jhdyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIuZGVzdHJveSgpOwoKICAgICAgICAgICAgbGV0IHNpemUgPSBuZXh0X2NvcHlfYnVmZmVyX3NpemUoaW5kaWNlc19yYXdfc2l6ZSk7CiAgICAgICAgICAgIGxldCBidWZmZXIgPSBjdHguZGV2aWNlLmNyZWF0ZV9idWZmZXIoJndncHU6OkJ1ZmZlckRlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6SW5kaWNlcyIpLAogICAgICAgICAgICAgICAgc2l6ZSwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OklOREVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogdHJ1ZSwKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJ1ZmZlci5zbGljZSguLikuZ2V0X21hcHBlZF9yYW5nZV9tdXQoKVsuLmluZGljZXNfcmF3LmxlbigpXQogICAgICAgICAgICAgICAgLmNvcHlfZnJvbV9zbGljZShpbmRpY2VzX3Jhdyk7CiAgICAgICAgICAgIGJ1ZmZlci51bm1hcCgpOwoKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIgPSBidWZmZXI7CiAgICAgICAgICAgIHNlbGYuaW5kZXhfYnVmZmVyX3NpemUgPSBzaXplOwogICAgICAgIH0KCiAgICAgICAgaWYgc2VsZi50ZXh0dXJlc192ZXJzaW9uICE9IHNlbGYuaW1hZ2VzLmVudHJpZXMubGVuKCkgewogICAgICAgICAgICBzZWxmLnRleHR1cmVzX3ZlcnNpb24gPSBzZWxmLmltYWdlcy5lbnRyaWVzLmxlbigpOwogICAgICAgICAgICBzZWxmLmxheW91dF9iaW5kX2dyb3VwID0KICAgICAgICAgICAgICAgIGN0eC5kZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgICAgIGxheW91dDogJnNlbGYubGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZTogd2dwdTo6QmluZGluZ1Jlc291cmNlOjpUZXh0dXJlVmlldygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICZzZWxmLmltYWdlcy50ZXh0dXJlX3ZpZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6UGlwZWxpbmUgdW5pZm9ybXMiKSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgcnBhc3Muc2V0X3BpcGVsaW5lKCZzZWxmLnBpcGVsaW5lKTsKICAgICAgICBycGFzcy5zZXRfYmluZF9ncm91cCgwLCAmc2VsZi5jb25zdGFudF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF9iaW5kX2dyb3VwKDEsICZzZWxmLmxheW91dF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF92ZXJ0ZXhfYnVmZmVyKDAsIHNlbGYudmVydGV4X2J1ZmZlci5zbGljZSguLikpOwogICAgICAgIHJwYXNzLnNldF9pbmRleF9idWZmZXIoc2VsZi5pbmRleF9idWZmZXIuc2xpY2UoLi4pLCB3Z3B1OjpJbmRleEZvcm1hdDo6VWludDMyKTsKICAgICAgICBycGFzcy5kcmF3X2luZGV4ZWQoMC4uKHNlbGYuZGxpc3QuaW5kaWNlcy5sZW4oKSBhcyB1MzIpLCAwLCAwLi4xKTsKCiAgICAgICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgICAgIC8vIHByaW50bG4hKCIgLSByaWNoX3RleHQ6OnJlbmRlcigpIGlzOiB7Oj99IiwgZHVyYXRpb24pOwogICAgfQp9CgojW2lubGluZV0KZm4gZHJhd19sYXlvdXQoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lczogJlZlYzxjcmF0ZTo6bGF5b3V0OjpCdWlsZGVyTGluZT4sCiAgICBwb3M6IChmMzIsIGYzMiksCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgIHJlY3Q6ICZTdWdhckRpbWVuc2lvbnMsCiAgICBncmFwaGljczogJm11dCBHcmFwaGljcywKKSB7CiAgICAvLyBsZXQgc3RhcnQgPSBzdGQ6OnRpbWU6Okluc3RhbnQ6Om5vdygpOwogICAgbGV0ICh4LCB5KSA9IHBvczsKICAgIGxldCAoaW1hZ2VfY2FjaGUsIGdseXBoc19jYWNoZSkgPSBjYWNoZXM7CiAgICBsZXQgZGVwdGggPSAwLjA7CiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6bmV3KCk7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udCA9IDA7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udF9zaXplID0gMC4wOwogICAgbGV0IGZvbnRfY29vcmRzOiAmW2kxNl0gPSAmWzAsIDAsIDAsIDBdOwogICAgaWYgbGV0IFNvbWUobGluZSkgPSBsaW5lcy5maXJzdCgpIHsKICAgICAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgICAgICBjdXJyZW50X2ZvbnQgPSBmaXJzdF9ydW4uc3Bhbi5mb250X2lkOwogICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IGZpcnN0X3J1bi5zaXplOwogICAgICAgIH0KICAgIH0KCiAgICBnbHlwaHNfY2FjaGUuc2V0X21heF9oZWlnaHQocmVjdC5oZWlnaHQgYXMgdTE2KTsKCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGxhc3RfcmVuZGVyZWRfZ3JhcGhpYyA9IEhhc2hTZXQ6Om5ldygpOwogICAgbGV0IG11dCBsaW5lX3kgPSAwLiArIHk7CiAgICBmb3IgbGluZSBpbiBsaW5lcyB7CiAgICAgICAgaWYgbGluZS5yZW5kZXJfZGF0YS5ydW5zLmlzX2VtcHR5KCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIGxldCBmaXJzdF9ydW4gPSAmbGluZS5yZW5kZXJfZGF0YS5ydW5zWzBdOwogICAgICAgIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICAgICAgbGV0IGRlc2NlbnQgPSBmaXJzdF9ydW4uZGVzY2VudC5yb3VuZCgpOwogICAgICAgIGxldCBsZWFkaW5nID0gKGZpcnN0X3J1bi5sZWFkaW5nKS5yb3VuZCgpICogMi47CiAgICAgICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICAgICAgbGV0IGJhc2VsaW5lID0gbGluZV95ICsgYXNjZW50OwogICAgICAgIGxpbmVfeSA9IGJhc2VsaW5lICsgZGVzY2VudDsKICAgICAgICBsZXQgcHkgPSBsaW5lX3k7CiAgICAgICAgbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICAgICAgZm9yIHJ1biBpbiAmbGluZS5yZW5kZXJfZGF0YS5ydW5zIHsKICAgICAgICAgICAgZ2x5cGhzLmNsZWFyKCk7CiAgICAgICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICAgICAgbGV0IGNoYXJfd2lkdGggPSBydW4uc3Bhbi53aWR0aDsKCiAgICAgICAgICAgIGxldCBydW5feCA9IHB4OwogICAgICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAgICAgbGV0IHggPSBweDsKICAgICAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgICAgICBweCArPSByZWN0LndpZHRoICogY2hhcl93aWR0aDsKICAgICAgICAgICAgICAgIGdseXBocy5wdXNoKEdseXBoIHsKICAgICAgICAgICAgICAgICAgICBpZDogZ2x5cGguc2ltcGxlX2RhdGEoKS4wLAogICAgICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICAgICAgeSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGZvbnRfc2l6ZTogcnVuLnNpemUsCiAgICAgICAgICAgICAgICBjb2xvcjogcnVuLnNwYW4uY29sb3IsCiAgICAgICAgICAgICAgICBjdXJzb3I6IHJ1bi5zcGFuLmN1cnNvciwKICAgICAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IHJ1bi5zcGFuLmJhY2tncm91bmRfY29sb3IsCiAgICAgICAgICAgICAgICBiYXNlbGluZTogcHksCiAgICAgICAgICAgICAgICB0b3BsaW5lOiBweSAtIGFzY2VudCwKICAgICAgICAgICAgICAgIGxpbmVfaGVpZ2h0LAogICAgICAgICAgICAgICAgYWR2YW5jZTogcHggLSBydW5feCwKICAgICAgICAgICAgICAgIGRlY29yYXRpb246IHJ1bi5zcGFuLmRlY29yYXRpb24sCiAgICAgICAgICAgICAgICBkZWNvcmF0aW9uX2NvbG9yOiBydW4uc3Bhbi5kZWNvcmF0aW9uX2NvbG9yLAogICAgICAgICAgICB9OwoKICAgICAgICAgICAgaWYgZm9udCAhPSBjdXJyZW50X2ZvbnQgfHwgc3R5bGUuZm9udF9zaXplICE9IGN1cnJlbnRfZm9udF9zaXplIHsKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udCA9IGZvbnQ7CiAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IHN0eWxlLmZvbnRfc2l6ZTsKCiAgICAgICAgICAgICAgICBzZXNzaW9uID0gZ2x5cGhzX2NhY2hlLnNlc3Npb24oCiAgICAgICAgICAgICAgICAgICAgaW1hZ2VfY2FjaGUsCiAgICAgICAgICAgICAgICAgICAgY3VycmVudF9mb250LAogICAgICAgICAgICAgICAgICAgIGZvbnRfbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgICAgICBzdHlsZS5mb250X3NpemUsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiBsZXQgU29tZShncmFwaGljKSA9IHJ1bi5zcGFuLm1lZGlhIHsKICAgICAgICAgICAgICAgIGlmICFsYXN0X3JlbmRlcmVkX2dyYXBoaWMuY29udGFpbnMoJmdyYXBoaWMuaWQpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0X3ggPSBncmFwaGljLm9mZnNldF94IGFzIGYzMjsKICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0X3kgPSBncmFwaGljLm9mZnNldF95IGFzIGYzMjsKCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MudG9wX2xheWVyLnB1c2goR3JhcGhpY1JlbmRlclJlcXVlc3QgewogICAgICAgICAgICAgICAgICAgICAgICBpZDogZ3JhcGhpYy5pZCwKICAgICAgICAgICAgICAgICAgICAgICAgcG9zX3g6IHJ1bl94IC0gb2Zmc2V0X3gsCiAgICAgICAgICAgICAgICAgICAgICAgIHBvc195OiBzdHlsZS50b3BsaW5lIC0gb2Zmc2V0X3ksCiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBOb25lLAogICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgbGFzdF9yZW5kZXJlZF9ncmFwaGljLmluc2VydChncmFwaGljLmlkKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29tcC5kcmF3X3J1bigKICAgICAgICAgICAgICAgICZtdXQgc2Vzc2lvbiwKICAgICAgICAgICAgICAgIFJlY3Q6Om5ldyhydW5feCwgcHksIHN0eWxlLmFkdmFuY2UsIDEuKSwKICAgICAgICAgICAgICAgIGRlcHRoLAogICAgICAgICAgICAgICAgJnN0eWxlLAogICAgICAgICAgICAgICAgJmdseXBocywKICAgICAgICAgICAgKTsKICAgICAgICB9CiAgICB9CgogICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgLy8gcHJpbnRsbiEoIiAtIGRyYXdfbGF5b3V0KCkgaXM6IHs6P31cbiIsIGR1cmF0aW9uKTsKfQoKI1tpbmxpbmVdCmZuIGZldGNoX2RpbWVuc2lvbnMoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lOiAmY3JhdGU6OmxheW91dDo6QnVpbGRlckxpbmUsCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKKSAtPiBTdWdhckRpbWVuc2lvbnMgewogICAgbGV0IHggPSAwLjsKICAgIGxldCB5ID0gMC47CgogICAgbGV0IChpbWFnZV9jYWNoZSwgZ2x5cGhzX2NhY2hlKSA9IGNhY2hlczsKICAgIGxldCBtdXQgY3VycmVudF9mb250ID0gMDsKICAgIGxldCBtdXQgY3VycmVudF9mb250X3NpemUgPSAwLjA7CiAgICBsZXQgZm9udF9jb29yZHM6ICZbaTE2XSA9ICZbMCwgMCwgMCwgMF07CiAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgIGN1cnJlbnRfZm9udCA9IGZpcnN0X3J1bi5zcGFuLmZvbnRfaWQ7CiAgICAgICAgY3VycmVudF9mb250X3NpemUgPSBmaXJzdF9ydW4uc2l6ZTsKICAgIH0KCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6d2l0aF9jYXBhY2l0eSgzKTsKICAgIGxldCBtdXQgZGltZW5zaW9uID0gU3VnYXJEaW1lbnNpb25zOjpkZWZhdWx0KCk7CiAgICBsZXQgZmlyc3RfcnVuID0gJmxpbmUucmVuZGVyX2RhdGEucnVuc1swXTsKICAgIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICBsZXQgZGVzY2VudCA9IGZpcnN0X3J1bi5kZXNjZW50LnJvdW5kKCk7CiAgICBsZXQgbGVhZGluZyA9IChmaXJzdF9ydW4ubGVhZGluZykucm91bmQoKSAqIDIuOwogICAgLy8gbGV0IG11dCBweCA9IHggKyBsaW5lLm9mZnNldCgpOwogICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICBsZXQgcHkgPSBhc2NlbnQgKyB5OwogICAgbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICBmb3IgcnVuIGluICZsaW5lLnJlbmRlcl9kYXRhLnJ1bnMgewogICAgICAgIGxldCBjaGFyX3dpZHRoID0gcnVuLnNwYW4ud2lkdGg7CgogICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICBsZXQgcnVuX3ggPSBweDsKICAgICAgICBnbHlwaHMuY2xlYXIoKTsKICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAvLyBsZXQgeCA9IHB4ICsgZ2x5cGgueDsKICAgICAgICAgICAgLy8gbGV0IHkgPSBweSAtIGdseXBoLnk7CiAgICAgICAgICAgIGxldCB4ID0gcHg7CiAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgIC8vIHB4ICs9IGdseXBoLmFkdmFuY2UKICAgICAgICAgICAgcHggKz0gZ2x5cGguc2ltcGxlX2RhdGEoKS4xICogY2hhcl93aWR0aDsKICAgICAgICAgICAgZ2x5cGhzLnB1c2goR2x5cGggewogICAgICAgICAgICAgICAgaWQ6IGdseXBoLnNpbXBsZV9kYXRhKCkuMCwKICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICB5LAogICAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgbGV0IGNvbG9yID0gcnVuLnNwYW4uY29sb3I7CgogICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgICAgICBmb250X3NpemU6IHJ1bi5zaXplLAogICAgICAgICAgICBjb2xvciwKICAgICAgICAgICAgY3Vyc29yOiBydW4uc3Bhbi5jdXJzb3IsCiAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IE5vbmUsCiAgICAgICAgICAgIGJhc2VsaW5lOiBweSwKICAgICAgICAgICAgdG9wbGluZTogcHkgLSBhc2NlbnQsCiAgICAgICAgICAgIGxpbmVfaGVpZ2h0LAogICAgICAgICAgICBhZHZhbmNlOiBweCAtIHJ1bl94LAogICAgICAgICAgICBkZWNvcmF0aW9uOiBOb25lLAogICAgICAgICAgICBkZWNvcmF0aW9uX2NvbG9yOiBOb25lLAogICAgICAgIH07CgogICAgICAgIGlmIHN0eWxlLmFkdmFuY2UgPiAwLiAmJiBsaW5lX2hlaWdodCA+IDAuIHsKICAgICAgICAgICAgZGltZW5zaW9uLndpZHRoID0gc3R5bGUuYWR2YW5jZS5yb3VuZCgpOwogICAgICAgICAgICBkaW1lbnNpb24uaGVpZ2h0ID0gbGluZV9oZWlnaHQucm91bmQoKTsKICAgICAgICB9CgogICAgICAgIGlmIGZvbnQgIT0gY3VycmVudF9mb250IHx8IHN0eWxlLmZvbnRfc2l6ZSAhPSBjdXJyZW50X2ZvbnRfc2l6ZSB7CiAgICAgICAgICAgIGN1cnJlbnRfZm9udCA9IGZvbnQ7CiAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplID0gc3R5bGUuZm9udF9zaXplOwoKICAgICAgICAgICAgc2Vzc2lvbiA9IGdseXBoc19jYWNoZS5zZXNzaW9uKAogICAgICAgICAgICAgICAgaW1hZ2VfY2FjaGUsCiAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgICAgICAgICBmb250X2xpYnJhcnksCiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgICAgICAgICApOwogICAgICAgIH0KCiAgICAgICAgY29tcC5kcmF3X3J1bigKICAgICAgICAgICAgJm11dCBzZXNzaW9uLAogICAgICAgICAgICBSZWN0OjpuZXcocnVuX3gsIHB5LCBzdHlsZS5hZHZhbmNlLCAxLiksCiAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgJnN0eWxlLAogICAgICAgICAgICAmZ2x5cGhzLAogICAgICAgICk7CiAgICB9CgogICAgZGltZW5zaW9uCn0KCiNbaW5saW5lXQpmbiBuZXh0X2NvcHlfYnVmZmVyX3NpemUoc2l6ZTogdTY0KSAtPiB1NjQgewogICAgbGV0IGFsaWduX21hc2sgPSB3Z3B1OjpDT1BZX0JVRkZFUl9BTElHTk1FTlQgLSAxOwogICAgKChzaXplLm5leHRfcG93ZXJfb2ZfdHdvKCkgKyBhbGlnbl9tYXNrKSAmICFhbGlnbl9tYXNrKQogICAgICAgIC5tYXgod2dwdTo6Q09QWV9CVUZGRVJfQUxJR05NRU5UKQp9CgAAAAAAAAAAuFYAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACZPwAAAAAAAJk/AAAAAAAAAAAAAAAA8L8" + ], + [ + 140, + 1, + "toggle_comment", + { + "block": false + }, + "AQAAALU/AAAAAAAAtT8AAAAAAAADAAAALy8g", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADXPwAAAAAAANc/AAAAAAAAAAAAAAAA8L8" + ], + [ + 149, + 1, + "paste", + null, + "AgAAAHpEAAAAAAAAgEQAAAAAAAAAAAAAgEQAAAAAAACARAAAAAAAAAsAAAByZWN0LmhlaWdodA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB6RAAAAAAAAIVEAAAAAAAAAAAAAAAA8L8" + ], + [ + 178, + 1, + "revert", + null, + "AwAAAAAAAAAAAAAAAAAAAAAAAACwVgAAbW9kIGJhdGNoOwptb2QgY29tcG9zaXRvcjsKbW9kIGltYWdlX2NhY2hlOwpwdWIgbW9kIHRleHQ7Cgp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OmNvcmU6Om9ydGhvZ3JhcGhpY19wcm9qZWN0aW9uOwp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OnJpY2hfdGV4dDo6aW1hZ2VfY2FjaGU6OntHbHlwaENhY2hlLCBJbWFnZUNhY2hlfTsKdXNlIGNyYXRlOjpjb250ZXh0OjpDb250ZXh0Owp1c2UgY3JhdGU6OmZvbnQ6OkZvbnRMaWJyYXJ5Owp1c2UgY3JhdGU6OmxheW91dDo6U3VnYXJEaW1lbnNpb25zOwp1c2UgY3JhdGU6OnN1Z2FybG9hZjo6Z3JhcGhpY3M6OkdyYXBoaWNSZW5kZXJSZXF1ZXN0Owp1c2UgY3JhdGU6OkdyYXBoaWNzOwp1c2UgY29tcG9zaXRvcjo6e0NvbXBvc2l0b3IsIERpc3BsYXlMaXN0LCBSZWN0LCBWZXJ0ZXh9Owp1c2Ugc3RkOjpjb2xsZWN0aW9uczo6SGFzaFNldDsKdXNlIHN0ZDo6e2JvcnJvdzo6Q293LCBtZW19Owp1c2UgdGV4dDo6e0dseXBoLCBUZXh0UnVuU3R5bGV9Owp1c2Ugd2dwdTo6dXRpbDo6RGV2aWNlRXh0OwoKLy8gTm90ZTogY3VycmVudGx5IGl0J3MgdXNpbmcgSW5kZXhlZCBkcmF3aW5nIGluc3RlYWQgb2YgSW5zdGFuY2UgZHJhd2luZyBjb3VsZCBiZSB3b3J0aCB0bwovLyBldmFsdWF0ZSBpZiB3b3VsZCBtYWtlIHNlbnNlIG1vdmUgdG8gaW5zdGFuY2UgZHJhd2luZyBpbnN0ZWFkCi8vIGh0dHBzOi8vbWF0aC5od3MuZWR1L2dyYXBoaWNzYm9vay9jOS9zMi5odG1sCi8vIGh0dHBzOi8vZG9jcy5ycy93Z3B1L2xhdGVzdC93Z3B1L2VudW0uVmVydGV4U3RlcE1vZGUuaHRtbAoKcHViIGNvbnN0IEJMRU5EOiBPcHRpb248d2dwdTo6QmxlbmRTdGF0ZT4gPSBTb21lKHdncHU6OkJsZW5kU3RhdGUgewogICAgY29sb3I6IHdncHU6OkJsZW5kQ29tcG9uZW50IHsKICAgICAgICBzcmNfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6U3JjQWxwaGEsCiAgICAgICAgZHN0X2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZU1pbnVzU3JjQWxwaGEsCiAgICAgICAgb3BlcmF0aW9uOiB3Z3B1OjpCbGVuZE9wZXJhdGlvbjo6QWRkLAogICAgfSwKICAgIGFscGhhOiB3Z3B1OjpCbGVuZENvbXBvbmVudCB7CiAgICAgICAgc3JjX2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZSwKICAgICAgICBkc3RfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6T25lTWludXNTcmNBbHBoYSwKICAgICAgICBvcGVyYXRpb246IHdncHU6OkJsZW5kT3BlcmF0aW9uOjpBZGQsCiAgICB9LAp9KTsKCnB1YiBzdHJ1Y3QgUmljaFRleHRCcnVzaCB7CiAgICB2ZXJ0ZXhfYnVmZmVyOiB3Z3B1OjpCdWZmZXIsCiAgICBjb25zdGFudF9iaW5kX2dyb3VwOiB3Z3B1OjpCaW5kR3JvdXAsCiAgICBsYXlvdXRfYmluZF9ncm91cDogd2dwdTo6QmluZEdyb3VwLAogICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0OiB3Z3B1OjpCaW5kR3JvdXBMYXlvdXQsCiAgICB0cmFuc2Zvcm06IHdncHU6OkJ1ZmZlciwKICAgIHBpcGVsaW5lOiB3Z3B1OjpSZW5kZXJQaXBlbGluZSwKICAgIGluZGV4X2J1ZmZlcjogd2dwdTo6QnVmZmVyLAogICAgaW5kZXhfYnVmZmVyX3NpemU6IHU2NCwKICAgIGN1cnJlbnRfdHJhbnNmb3JtOiBbZjMyOyAxNl0sCiAgICBjb21wOiBDb21wb3NpdG9yLAogICAgZGxpc3Q6IERpc3BsYXlMaXN0LAogICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXI6IHVzaXplLAogICAgdGV4dHVyZXNfdmVyc2lvbjogdXNpemUsCiAgICBpbWFnZXM6IEltYWdlQ2FjaGUsCiAgICBnbHlwaHM6IEdseXBoQ2FjaGUsCn0KCmltcGwgUmljaFRleHRCcnVzaCB7CiAgICBwdWIgZm4gbmV3KGNvbnRleHQ6ICZDb250ZXh0KSAtPiBTZWxmIHsKICAgICAgICBsZXQgZGV2aWNlID0gJmNvbnRleHQuZGV2aWNlOwogICAgICAgIGxldCBkbGlzdCA9IERpc3BsYXlMaXN0OjpuZXcoKTsKICAgICAgICBsZXQgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIgPSAyXzAwMDsKCiAgICAgICAgbGV0IGN1cnJlbnRfdHJhbnNmb3JtID0KICAgICAgICAgICAgb3J0aG9ncmFwaGljX3Byb2plY3Rpb24oY29udGV4dC5zaXplLndpZHRoLCBjb250ZXh0LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtID0gZGV2aWNlLmNyZWF0ZV9idWZmZXJfaW5pdCgmd2dwdTo6dXRpbDo6QnVmZmVySW5pdERlc2NyaXB0b3IgewogICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgY29udGVudHM6IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZjdXJyZW50X3RyYW5zZm9ybSksCiAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlVOSUZPUk0gfCB3Z3B1OjpCdWZmZXJVc2FnZXM6OkNPUFlfRFNULAogICAgICAgIH0pOwoKICAgICAgICAvLyBDcmVhdGUgcGlwZWxpbmUgbGF5b3V0CiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9iaW5kX2dyb3VwX2xheW91dCgmd2dwdTo6QmluZEdyb3VwTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbCiAgICAgICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwTGF5b3V0RW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmlsaXR5OiB3Z3B1OjpTaGFkZXJTdGFnZXM6OlZFUlRFWCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpCdWZmZXIgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJ1ZmZlckJpbmRpbmdUeXBlOjpVbmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzX2R5bmFtaWNfb2Zmc2V0OiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9iaW5kaW5nX3NpemU6IHdncHU6OkJ1ZmZlclNpemU6Om5ldyhtZW06OnNpemVfb2Y6OjwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZjMyOyAxNl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzIHdncHU6OkJ1ZmZlckFkZHJlc3MpLAogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogTm9uZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgYmluZGluZzogMSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogd2dwdTo6U2hhZGVyU3RhZ2VzOjpWRVJURVgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgd2dwdTo6U2hhZGVyU3RhZ2VzOjpGUkFHTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpTYW1wbGVyKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2dwdTo6U2FtcGxlckJpbmRpbmdUeXBlOjpGaWx0ZXJpbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGxheW91dF9iaW5kX2dyb3VwX2xheW91dCA9CiAgICAgICAgICAgIGRldmljZS5jcmVhdGVfYmluZF9ncm91cF9sYXlvdXQoJndncHU6OkJpbmRHcm91cExheW91dERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgICAgICBlbnRyaWVzOiAmW3dncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6IHdncHU6OlNoYWRlclN0YWdlczo6RlJBR01FTlQsCiAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpUZXh0dXJlIHsKICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX3R5cGU6IHdncHU6OlRleHR1cmVTYW1wbGVUeXBlOjpGbG9hdCB7IGZpbHRlcmFibGU6IHRydWUgfSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlld19kaW1lbnNpb246IHdncHU6OlRleHR1cmVWaWV3RGltZW5zaW9uOjpEMiwKICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlzYW1wbGVkOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgIH0pOwoKICAgICAgICBsZXQgcGlwZWxpbmVfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9waXBlbGluZV9sYXlvdXQoJndncHU6OlBpcGVsaW5lTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIHB1c2hfY29uc3RhbnRfcmFuZ2VzOiAmW10sCiAgICAgICAgICAgICAgICBiaW5kX2dyb3VwX2xheW91dHM6ICZbCiAgICAgICAgICAgICAgICAgICAgJmNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgICZsYXlvdXRfYmluZF9ncm91cF9sYXlvdXQsCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGltYWdlcyA9IEltYWdlQ2FjaGU6Om5ldyhjb250ZXh0KTsKCiAgICAgICAgbGV0IHNhbXBsZXIgPSBkZXZpY2UuY3JlYXRlX3NhbXBsZXIoJndncHU6OlNhbXBsZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3U6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3Y6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3c6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgbWFnX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWluX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWlwbWFwX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbG9kX21pbl9jbGFtcDogMGYzMiwKICAgICAgICAgICAgbG9kX21heF9jbGFtcDogMGYzMiwKICAgICAgICAgICAgLi5EZWZhdWx0OjpkZWZhdWx0KCkKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXAgPSBkZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICBsYXlvdXQ6ICZjb25zdGFudF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlsKICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHJlc291cmNlOiB3Z3B1OjpCaW5kaW5nUmVzb3VyY2U6OkJ1ZmZlcih3Z3B1OjpCdWZmZXJCaW5kaW5nIHsKICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiAmdHJhbnNmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgIGJpbmRpbmc6IDEsCiAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6U2FtcGxlcigmc2FtcGxlciksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICBdLAogICAgICAgICAgICBsYWJlbDogU29tZSgicmljaF90ZXh0Ojpjb25zdGFudF9iaW5kX2dyb3VwIiksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBsYXlvdXRfYmluZF9ncm91cCA9IGRldmljZS5jcmVhdGVfYmluZF9ncm91cCgmd2dwdTo6QmluZEdyb3VwRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxheW91dDogJmxheW91dF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlt3Z3B1OjpCaW5kR3JvdXBFbnRyeSB7CiAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6VGV4dHVyZVZpZXcoJmltYWdlcy50ZXh0dXJlX3ZpZXcpLAogICAgICAgICAgICB9XSwKICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6bGF5b3V0X2JpbmRfZ3JvdXAiKSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHNoYWRlciA9IGRldmljZS5jcmVhdGVfc2hhZGVyX21vZHVsZSh3Z3B1OjpTaGFkZXJNb2R1bGVEZXNjcmlwdG9yIHsKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIHNvdXJjZTogd2dwdTo6U2hhZGVyU291cmNlOjpXZ3NsKENvdzo6Qm9ycm93ZWQoaW5jbHVkZV9zdHIhKAogICAgICAgICAgICAgICAgInJpY2hfdGV4dC53Z3NsIgogICAgICAgICAgICApKSksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBwaXBlbGluZSA9IGRldmljZS5jcmVhdGVfcmVuZGVyX3BpcGVsaW5lKCZ3Z3B1OjpSZW5kZXJQaXBlbGluZURlc2NyaXB0b3IgewogICAgICAgICAgICBjYWNoZTogTm9uZSwKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIGxheW91dDogU29tZSgmcGlwZWxpbmVfbGF5b3V0KSwKICAgICAgICAgICAgdmVydGV4OiB3Z3B1OjpWZXJ0ZXhTdGF0ZSB7CiAgICAgICAgICAgICAgICBjb21waWxhdGlvbl9vcHRpb25zOiB3Z3B1OjpQaXBlbGluZUNvbXBpbGF0aW9uT3B0aW9uczo6ZGVmYXVsdCgpLAogICAgICAgICAgICAgICAgbW9kdWxlOiAmc2hhZGVyLAogICAgICAgICAgICAgICAgZW50cnlfcG9pbnQ6IFNvbWUoInZzX21haW4iKSwKICAgICAgICAgICAgICAgIGJ1ZmZlcnM6ICZbd2dwdTo6VmVydGV4QnVmZmVyTGF5b3V0IHsKICAgICAgICAgICAgICAgICAgICBhcnJheV9zdHJpZGU6IG1lbTo6c2l6ZV9vZjo6PFZlcnRleD4oKSBhcyB1NjQsCiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLnJzL3dncHUvbGF0ZXN0L3dncHUvZW51bS5WZXJ0ZXhTdGVwTW9kZS5odG1sCiAgICAgICAgICAgICAgICAgICAgc3RlcF9tb2RlOiB3Z3B1OjpWZXJ0ZXhTdGVwTW9kZTo6VmVydGV4LAogICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6ICZ3Z3B1Ojp2ZXJ0ZXhfYXR0cl9hcnJheSEoCiAgICAgICAgICAgICAgICAgICAgICAgIDAgPT4gRmxvYXQzMngzLAogICAgICAgICAgICAgICAgICAgICAgICAxID0+IEZsb2F0MzJ4NCwKICAgICAgICAgICAgICAgICAgICAgICAgMiA9PiBGbG9hdDMyeDIsCiAgICAgICAgICAgICAgICAgICAgICAgIDMgPT4gU2ludDMyeDIsCiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIH1dLAogICAgICAgICAgICB9LAogICAgICAgICAgICBmcmFnbWVudDogU29tZSh3Z3B1OjpGcmFnbWVudFN0YXRlIHsKICAgICAgICAgICAgICAgIGNvbXBpbGF0aW9uX29wdGlvbnM6IHdncHU6OlBpcGVsaW5lQ29tcGlsYXRpb25PcHRpb25zOjpkZWZhdWx0KCksCiAgICAgICAgICAgICAgICBtb2R1bGU6ICZzaGFkZXIsCiAgICAgICAgICAgICAgICBlbnRyeV9wb2ludDogU29tZSgiZnNfbWFpbiIpLAogICAgICAgICAgICAgICAgdGFyZ2V0czogJltTb21lKHdncHU6OkNvbG9yVGFyZ2V0U3RhdGUgewogICAgICAgICAgICAgICAgICAgIGZvcm1hdDogY29udGV4dC5mb3JtYXQsCiAgICAgICAgICAgICAgICAgICAgYmxlbmQ6IEJMRU5ELAogICAgICAgICAgICAgICAgICAgIHdyaXRlX21hc2s6IHdncHU6OkNvbG9yV3JpdGVzOjpBTEwsCiAgICAgICAgICAgICAgICB9KV0sCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICBwcmltaXRpdmU6IHdncHU6OlByaW1pdGl2ZVN0YXRlIHsKICAgICAgICAgICAgICAgIHRvcG9sb2d5OiB3Z3B1OjpQcmltaXRpdmVUb3BvbG9neTo6VHJpYW5nbGVMaXN0LAogICAgICAgICAgICAgICAgc3RyaXBfaW5kZXhfZm9ybWF0OiBOb25lLAogICAgICAgICAgICAgICAgZnJvbnRfZmFjZTogd2dwdTo6RnJvbnRGYWNlOjpDY3csCiAgICAgICAgICAgICAgICBjdWxsX21vZGU6IE5vbmUsCiAgICAgICAgICAgICAgICBwb2x5Z29uX21vZGU6IHdncHU6OlBvbHlnb25Nb2RlOjpGaWxsLAogICAgICAgICAgICAgICAgdW5jbGlwcGVkX2RlcHRoOiBmYWxzZSwKICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZTogZmFsc2UsCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGRlcHRoX3N0ZW5jaWw6IE5vbmUsCiAgICAgICAgICAgIG11bHRpc2FtcGxlOiB3Z3B1OjpNdWx0aXNhbXBsZVN0YXRlOjpkZWZhdWx0KCksCiAgICAgICAgICAgIG11bHRpdmlldzogTm9uZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHZlcnRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6Okluc3RhbmNlcyBCdWZmZXIiKSwKICAgICAgICAgICAgc2l6ZTogbWVtOjpzaXplX29mOjo8VmVydGV4PigpIGFzIHU2NCAqIHN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgdXNhZ2U6IHdncHU6OkJ1ZmZlclVzYWdlczo6VkVSVEVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgbWFwcGVkX2F0X2NyZWF0aW9uOiBmYWxzZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplOiAmW3UzMl0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmZGxpc3QuaW5kaWNlcyk7CiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplID0gaW5kZXhfYnVmZmVyX3NpemUubGVuKCkgYXMgdTY0OwogICAgICAgIGxldCBpbmRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6OkluZGljZXMgQnVmZmVyIiksCiAgICAgICAgICAgIHNpemU6IGluZGV4X2J1ZmZlcl9zaXplLAogICAgICAgICAgICB1c2FnZTogd2dwdTo6QnVmZmVyVXNhZ2VzOjpJTkRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogZmFsc2UsCiAgICAgICAgfSk7CgogICAgICAgIFJpY2hUZXh0QnJ1c2ggewogICAgICAgICAgICBsYXlvdXRfYmluZF9ncm91cCwKICAgICAgICAgICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICBjb25zdGFudF9iaW5kX2dyb3VwLAogICAgICAgICAgICBpbmRleF9idWZmZXJfc2l6ZSwKICAgICAgICAgICAgaW5kZXhfYnVmZmVyLAogICAgICAgICAgICBjb21wOiBDb21wb3NpdG9yOjpuZXcoKSwKICAgICAgICAgICAgaW1hZ2VzLAogICAgICAgICAgICB0ZXh0dXJlc192ZXJzaW9uOiAwLAogICAgICAgICAgICBnbHlwaHM6IEdseXBoQ2FjaGU6Om5ldygpLAogICAgICAgICAgICBkbGlzdCwKICAgICAgICAgICAgdHJhbnNmb3JtLAogICAgICAgICAgICBwaXBlbGluZSwKICAgICAgICAgICAgdmVydGV4X2J1ZmZlciwKICAgICAgICAgICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIsCiAgICAgICAgICAgIGN1cnJlbnRfdHJhbnNmb3JtLAogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBwcmVwYXJlKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBjb250ZXh0OiAmbXV0IGNyYXRlOjpjb250ZXh0OjpDb250ZXh0LAogICAgICAgIHN0YXRlOiAmY3JhdGU6OnN1Z2FybG9hZjo6c3RhdGU6OlN1Z2FyU3RhdGUsCiAgICAgICAgZ3JhcGhpY3M6ICZtdXQgR3JhcGhpY3MsCiAgICApIHsKICAgICAgICBpZiBzdGF0ZS5yaWNoX3RleHRzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHNlbGYuY29tcC5iZWdpbigpOwogICAgICAgIGxldCBsaWJyYXJ5ID0gc3RhdGUuY29tcG9zaXRvcnMuYWR2YW5jZWQuZm9udF9saWJyYXJ5KCk7CiAgICAgICAgZm9yIHJpY2hfdGV4dCBpbiAmc3RhdGUucmljaF90ZXh0cyB7CiAgICAgICAgICAgIGlmIGxldCBTb21lKHJ0KSA9IHN0YXRlLmNvbXBvc2l0b3JzLmFkdmFuY2VkLmdldF9yaWNoX3RleHQoJnJpY2hfdGV4dC5pZCkgewogICAgICAgICAgICAgICAgbGV0IHBvc2l0aW9uID0gKAogICAgICAgICAgICAgICAgICAgIHJpY2hfdGV4dC5wb3NpdGlvblswXSAqIHN0YXRlLnN0eWxlLnNjYWxlX2ZhY3RvciwKICAgICAgICAgICAgICAgICAgICByaWNoX3RleHQucG9zaXRpb25bMV0gKiBzdGF0ZS5zdHlsZS5zY2FsZV9mYWN0b3IsCiAgICAgICAgICAgICAgICApOwoKICAgICAgICAgICAgICAgIGRyYXdfbGF5b3V0KAogICAgICAgICAgICAgICAgICAgICZtdXQgc2VsZi5jb21wLAogICAgICAgICAgICAgICAgICAgICgmbXV0IHNlbGYuaW1hZ2VzLCAmbXV0IHNlbGYuZ2x5cGhzKSwKICAgICAgICAgICAgICAgICAgICAmcnQubGluZXMsCiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgICAgICAgICAgbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICAmcnQubGF5b3V0LmRpbWVuc2lvbnMsCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgc2VsZi5pbWFnZXMucHJvY2Vzc19hdGxhc2VzKGNvbnRleHQpOwogICAgICAgIHNlbGYuY29tcC5maW5pc2goJm11dCBzZWxmLmRsaXN0KTsKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBkaW1lbnNpb25zKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgICAgICByZW5kZXJfZGF0YTogJmNyYXRlOjpsYXlvdXQ6OkJ1aWxkZXJMaW5lLAogICAgKSAtPiBPcHRpb248U3VnYXJEaW1lbnNpb25zPiB7CiAgICAgICAgc2VsZi5jb21wLmJlZ2luKCk7CgogICAgICAgIGxldCBkaW1lbnNpb24gPSBmZXRjaF9kaW1lbnNpb25zKAogICAgICAgICAgICAmbXV0IHNlbGYuY29tcCwKICAgICAgICAgICAgKCZtdXQgc2VsZi5pbWFnZXMsICZtdXQgc2VsZi5nbHlwaHMpLAogICAgICAgICAgICByZW5kZXJfZGF0YSwKICAgICAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgICk7CiAgICAgICAgaWYgZGltZW5zaW9uLmhlaWdodCA+IDAuICYmIGRpbWVuc2lvbi53aWR0aCA+IDAuIHsKICAgICAgICAgICAgU29tZShkaW1lbnNpb24pCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgTm9uZQogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiByZXNldCgmbXV0IHNlbGYpIHsKICAgICAgICBzZWxmLmdseXBocyA9IEdseXBoQ2FjaGU6Om5ldygpOwogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHJlbmRlcjwncGFzcz4oCiAgICAgICAgJidwYXNzIG11dCBzZWxmLAogICAgICAgIGN0eDogJm11dCBDb250ZXh0LAogICAgICAgIHJwYXNzOiAmbXV0IHdncHU6OlJlbmRlclBhc3M8J3Bhc3M+LAogICAgKSB7CiAgICAgICAgLy8gbGV0IHN0YXJ0ID0gc3RkOjp0aW1lOjpJbnN0YW50Ojpub3coKTsKICAgICAgICAvLyBUaGVyZSdzIG5vdGhpbmcgdG8gcmVuZGVyCiAgICAgICAgaWYgc2VsZi5kbGlzdC52ZXJ0aWNlcy5pc19lbXB0eSgpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgbGV0IHF1ZXVlID0gJm11dCBjdHgucXVldWU7CgogICAgICAgIGxldCB0cmFuc2Zvcm0gPSBvcnRob2dyYXBoaWNfcHJvamVjdGlvbihjdHguc2l6ZS53aWR0aCwgY3R4LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtX2hhc19jaGFuZ2VkID0gdHJhbnNmb3JtICE9IHNlbGYuY3VycmVudF90cmFuc2Zvcm07CgogICAgICAgIGlmIHRyYW5zZm9ybV9oYXNfY2hhbmdlZCB7CiAgICAgICAgICAgIHF1ZXVlLndyaXRlX2J1ZmZlcigmc2VsZi50cmFuc2Zvcm0sIDAsIGJ5dGVtdWNrOjpieXRlc19vZigmdHJhbnNmb3JtKSk7CiAgICAgICAgICAgIHNlbGYuY3VycmVudF90cmFuc2Zvcm0gPSB0cmFuc2Zvcm07CiAgICAgICAgfQoKICAgICAgICBpZiBzZWxmLmRsaXN0LnZlcnRpY2VzLmxlbigpID4gc2VsZi5zdXBwb3J0ZWRfdmVydGV4X2J1ZmZlciB7CiAgICAgICAgICAgIHNlbGYudmVydGV4X2J1ZmZlci5kZXN0cm95KCk7CgogICAgICAgICAgICBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyID0gc2VsZi5kbGlzdC52ZXJ0aWNlcy5sZW4oKTsKICAgICAgICAgICAgc2VsZi52ZXJ0ZXhfYnVmZmVyID0gY3R4LmRldmljZS5jcmVhdGVfYnVmZmVyKCZ3Z3B1OjpCdWZmZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgICAgIGxhYmVsOiBTb21lKCJzdWdhcmxvYWY6OnJpY2hfdGV4dDo6UGlwZWxpbmUgaW5zdGFuY2VzIiksCiAgICAgICAgICAgICAgICBzaXplOiBtZW06OnNpemVfb2Y6OjxWZXJ0ZXg+KCkgYXMgdTY0CiAgICAgICAgICAgICAgICAgICAgKiBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlZFUlRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgICAgICBtYXBwZWRfYXRfY3JlYXRpb246IGZhbHNlLAogICAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIGxldCB2ZXJ0aWNlc19ieXRlczogJlt1OF0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmc2VsZi5kbGlzdC52ZXJ0aWNlcyk7CiAgICAgICAgaWYgIXZlcnRpY2VzX2J5dGVzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYudmVydGV4X2J1ZmZlciwgMCwgdmVydGljZXNfYnl0ZXMpOwogICAgICAgIH0KCiAgICAgICAgbGV0IGluZGljZXNfcmF3OiAmW3U4XSA9IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZzZWxmLmRsaXN0LmluZGljZXMpOwogICAgICAgIGxldCBpbmRpY2VzX3Jhd19zaXplID0gaW5kaWNlc19yYXcubGVuKCkgYXMgdTY0OwoKICAgICAgICBpZiBzZWxmLmluZGV4X2J1ZmZlcl9zaXplID49IGluZGljZXNfcmF3X3NpemUgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYuaW5kZXhfYnVmZmVyLCAwLCBpbmRpY2VzX3Jhdyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIuZGVzdHJveSgpOwoKICAgICAgICAgICAgbGV0IHNpemUgPSBuZXh0X2NvcHlfYnVmZmVyX3NpemUoaW5kaWNlc19yYXdfc2l6ZSk7CiAgICAgICAgICAgIGxldCBidWZmZXIgPSBjdHguZGV2aWNlLmNyZWF0ZV9idWZmZXIoJndncHU6OkJ1ZmZlckRlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6SW5kaWNlcyIpLAogICAgICAgICAgICAgICAgc2l6ZSwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OklOREVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogdHJ1ZSwKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJ1ZmZlci5zbGljZSguLikuZ2V0X21hcHBlZF9yYW5nZV9tdXQoKVsuLmluZGljZXNfcmF3LmxlbigpXQogICAgICAgICAgICAgICAgLmNvcHlfZnJvbV9zbGljZShpbmRpY2VzX3Jhdyk7CiAgICAgICAgICAgIGJ1ZmZlci51bm1hcCgpOwoKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIgPSBidWZmZXI7CiAgICAgICAgICAgIHNlbGYuaW5kZXhfYnVmZmVyX3NpemUgPSBzaXplOwogICAgICAgIH0KCiAgICAgICAgaWYgc2VsZi50ZXh0dXJlc192ZXJzaW9uICE9IHNlbGYuaW1hZ2VzLmVudHJpZXMubGVuKCkgewogICAgICAgICAgICBzZWxmLnRleHR1cmVzX3ZlcnNpb24gPSBzZWxmLmltYWdlcy5lbnRyaWVzLmxlbigpOwogICAgICAgICAgICBzZWxmLmxheW91dF9iaW5kX2dyb3VwID0KICAgICAgICAgICAgICAgIGN0eC5kZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgICAgIGxheW91dDogJnNlbGYubGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZTogd2dwdTo6QmluZGluZ1Jlc291cmNlOjpUZXh0dXJlVmlldygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICZzZWxmLmltYWdlcy50ZXh0dXJlX3ZpZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6UGlwZWxpbmUgdW5pZm9ybXMiKSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgcnBhc3Muc2V0X3BpcGVsaW5lKCZzZWxmLnBpcGVsaW5lKTsKICAgICAgICBycGFzcy5zZXRfYmluZF9ncm91cCgwLCAmc2VsZi5jb25zdGFudF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF9iaW5kX2dyb3VwKDEsICZzZWxmLmxheW91dF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF92ZXJ0ZXhfYnVmZmVyKDAsIHNlbGYudmVydGV4X2J1ZmZlci5zbGljZSguLikpOwogICAgICAgIHJwYXNzLnNldF9pbmRleF9idWZmZXIoc2VsZi5pbmRleF9idWZmZXIuc2xpY2UoLi4pLCB3Z3B1OjpJbmRleEZvcm1hdDo6VWludDMyKTsKICAgICAgICBycGFzcy5kcmF3X2luZGV4ZWQoMC4uKHNlbGYuZGxpc3QuaW5kaWNlcy5sZW4oKSBhcyB1MzIpLCAwLCAwLi4xKTsKCiAgICAgICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgICAgIC8vIHByaW50bG4hKCIgLSByaWNoX3RleHQ6OnJlbmRlcigpIGlzOiB7Oj99IiwgZHVyYXRpb24pOwogICAgfQp9CgojW2lubGluZV0KZm4gZHJhd19sYXlvdXQoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lczogJlZlYzxjcmF0ZTo6bGF5b3V0OjpCdWlsZGVyTGluZT4sCiAgICBwb3M6IChmMzIsIGYzMiksCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgIHJlY3Q6ICZTdWdhckRpbWVuc2lvbnMsCiAgICBncmFwaGljczogJm11dCBHcmFwaGljcywKKSB7CiAgICAvLyBsZXQgc3RhcnQgPSBzdGQ6OnRpbWU6Okluc3RhbnQ6Om5vdygpOwogICAgbGV0ICh4LCB5KSA9IHBvczsKICAgIGxldCAoaW1hZ2VfY2FjaGUsIGdseXBoc19jYWNoZSkgPSBjYWNoZXM7CiAgICBsZXQgZGVwdGggPSAwLjA7CiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6bmV3KCk7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udCA9IDA7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udF9zaXplID0gMC4wOwogICAgbGV0IGZvbnRfY29vcmRzOiAmW2kxNl0gPSAmWzAsIDAsIDAsIDBdOwogICAgaWYgbGV0IFNvbWUobGluZSkgPSBsaW5lcy5maXJzdCgpIHsKICAgICAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgICAgICBjdXJyZW50X2ZvbnQgPSBmaXJzdF9ydW4uc3Bhbi5mb250X2lkOwogICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IGZpcnN0X3J1bi5zaXplOwogICAgICAgIH0KICAgIH0KCiAgICBnbHlwaHNfY2FjaGUuc2V0X21heF9oZWlnaHQocmVjdC5oZWlnaHQgYXMgdTE2KTsKCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGxhc3RfcmVuZGVyZWRfZ3JhcGhpYyA9IEhhc2hTZXQ6Om5ldygpOwogICAgbGV0IG11dCBsaW5lX3kgPSAwLiArIHk7CiAgICBmb3IgbGluZSBpbiBsaW5lcyB7CiAgICAgICAgaWYgbGluZS5yZW5kZXJfZGF0YS5ydW5zLmlzX2VtcHR5KCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIGxldCBmaXJzdF9ydW4gPSAmbGluZS5yZW5kZXJfZGF0YS5ydW5zWzBdOwogICAgICAgIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICAgICAgLy8gbGV0IGRlc2NlbnQgPSBmaXJzdF9ydW4uZGVzY2VudC5yb3VuZCgpOwogICAgICAgIC8vIGxldCBsZWFkaW5nID0gKGZpcnN0X3J1bi5sZWFkaW5nKS5yb3VuZCgpICogMi47CiAgICAgICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICAgICAgLy8gbGV0IGJhc2VsaW5lID0gbGluZV95ICsgYXNjZW50OwogICAgICAgIC8vIGxpbmVfeSA9IGJhc2VsaW5lICsgZGVzY2VudDsKICAgICAgICBsaW5lX3kgPSBsaW5lX3kgKyByZWN0LmhlaWdodDsKICAgICAgICBsZXQgcHkgPSBsaW5lX3k7CiAgICAgICAgLy8gbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICAgICAgbGV0IGxpbmVfaGVpZ2h0ID0gcmVjdC5oZWlnaHQ7CiAgICAgICAgZm9yIHJ1biBpbiAmbGluZS5yZW5kZXJfZGF0YS5ydW5zIHsKICAgICAgICAgICAgZ2x5cGhzLmNsZWFyKCk7CiAgICAgICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICAgICAgbGV0IGNoYXJfd2lkdGggPSBydW4uc3Bhbi53aWR0aDsKCiAgICAgICAgICAgIGxldCBydW5feCA9IHB4OwogICAgICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAgICAgbGV0IHggPSBweDsKICAgICAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgICAgICBweCArPSByZWN0LndpZHRoICogY2hhcl93aWR0aDsKICAgICAgICAgICAgICAgIGdseXBocy5wdXNoKEdseXBoIHsKICAgICAgICAgICAgICAgICAgICBpZDogZ2x5cGguc2ltcGxlX2RhdGEoKS4wLAogICAgICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICAgICAgeSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGZvbnRfc2l6ZTogcnVuLnNpemUsCiAgICAgICAgICAgICAgICBjb2xvcjogcnVuLnNwYW4uY29sb3IsCiAgICAgICAgICAgICAgICBjdXJzb3I6IHJ1bi5zcGFuLmN1cnNvciwKICAgICAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IHJ1bi5zcGFuLmJhY2tncm91bmRfY29sb3IsCiAgICAgICAgICAgICAgICBiYXNlbGluZTogcHksCiAgICAgICAgICAgICAgICB0b3BsaW5lOiBweSAtIGFzY2VudCwKICAgICAgICAgICAgICAgIGxpbmVfaGVpZ2h0LAogICAgICAgICAgICAgICAgYWR2YW5jZTogcHggLSBydW5feCwKICAgICAgICAgICAgICAgIGRlY29yYXRpb246IHJ1bi5zcGFuLmRlY29yYXRpb24sCiAgICAgICAgICAgICAgICBkZWNvcmF0aW9uX2NvbG9yOiBydW4uc3Bhbi5kZWNvcmF0aW9uX2NvbG9yLAogICAgICAgICAgICB9OwoKICAgICAgICAgICAgaWYgZm9udCAhPSBjdXJyZW50X2ZvbnQgfHwgc3R5bGUuZm9udF9zaXplICE9IGN1cnJlbnRfZm9udF9zaXplIHsKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udCA9IGZvbnQ7CiAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IHN0eWxlLmZvbnRfc2l6ZTsKCiAgICAgICAgICAgICAgICBzZXNzaW9uID0gZ2x5cGhzX2NhY2hlLnNlc3Npb24oCiAgICAgICAgICAgICAgICAgICAgaW1hZ2VfY2FjaGUsCiAgICAgICAgICAgICAgICAgICAgY3VycmVudF9mb250LAogICAgICAgICAgICAgICAgICAgIGZvbnRfbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgICAgICBzdHlsZS5mb250X3NpemUsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiBsZXQgU29tZShncmFwaGljKSA9IHJ1bi5zcGFuLm1lZGlhIHsKICAgICAgICAgICAgICAgIGlmICFsYXN0X3JlbmRlcmVkX2dyYXBoaWMuY29udGFpbnMoJmdyYXBoaWMuaWQpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0X3ggPSBncmFwaGljLm9mZnNldF94IGFzIGYzMjsKICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0X3kgPSBncmFwaGljLm9mZnNldF95IGFzIGYzMjsKCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MudG9wX2xheWVyLnB1c2goR3JhcGhpY1JlbmRlclJlcXVlc3QgewogICAgICAgICAgICAgICAgICAgICAgICBpZDogZ3JhcGhpYy5pZCwKICAgICAgICAgICAgICAgICAgICAgICAgcG9zX3g6IHJ1bl94IC0gb2Zmc2V0X3gsCiAgICAgICAgICAgICAgICAgICAgICAgIHBvc195OiBzdHlsZS50b3BsaW5lIC0gb2Zmc2V0X3ksCiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBOb25lLAogICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgbGFzdF9yZW5kZXJlZF9ncmFwaGljLmluc2VydChncmFwaGljLmlkKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29tcC5kcmF3X3J1bigKICAgICAgICAgICAgICAgICZtdXQgc2Vzc2lvbiwKICAgICAgICAgICAgICAgIFJlY3Q6Om5ldyhydW5feCwgcHksIHN0eWxlLmFkdmFuY2UsIDEuKSwKICAgICAgICAgICAgICAgIGRlcHRoLAogICAgICAgICAgICAgICAgJnN0eWxlLAogICAgICAgICAgICAgICAgJmdseXBocywKICAgICAgICAgICAgKTsKICAgICAgICB9CiAgICB9CgogICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgLy8gcHJpbnRsbiEoIiAtIGRyYXdfbGF5b3V0KCkgaXM6IHs6P31cbiIsIGR1cmF0aW9uKTsKfQoKI1tpbmxpbmVdCmZuIGZldGNoX2RpbWVuc2lvbnMoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lOiAmY3JhdGU6OmxheW91dDo6QnVpbGRlckxpbmUsCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKKSAtPiBTdWdhckRpbWVuc2lvbnMgewogICAgbGV0IHggPSAwLjsKICAgIGxldCB5ID0gMC47CgogICAgbGV0IChpbWFnZV9jYWNoZSwgZ2x5cGhzX2NhY2hlKSA9IGNhY2hlczsKICAgIGxldCBtdXQgY3VycmVudF9mb250ID0gMDsKICAgIGxldCBtdXQgY3VycmVudF9mb250X3NpemUgPSAwLjA7CiAgICBsZXQgZm9udF9jb29yZHM6ICZbaTE2XSA9ICZbMCwgMCwgMCwgMF07CiAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgIGN1cnJlbnRfZm9udCA9IGZpcnN0X3J1bi5zcGFuLmZvbnRfaWQ7CiAgICAgICAgY3VycmVudF9mb250X3NpemUgPSBmaXJzdF9ydW4uc2l6ZTsKICAgIH0KCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6d2l0aF9jYXBhY2l0eSgzKTsKICAgIGxldCBtdXQgZGltZW5zaW9uID0gU3VnYXJEaW1lbnNpb25zOjpkZWZhdWx0KCk7CiAgICBsZXQgZmlyc3RfcnVuID0gJmxpbmUucmVuZGVyX2RhdGEucnVuc1swXTsKICAgIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICBsZXQgZGVzY2VudCA9IGZpcnN0X3J1bi5kZXNjZW50LnJvdW5kKCk7CiAgICBsZXQgbGVhZGluZyA9IChmaXJzdF9ydW4ubGVhZGluZykucm91bmQoKSAqIDIuOwogICAgLy8gbGV0IG11dCBweCA9IHggKyBsaW5lLm9mZnNldCgpOwogICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICBsZXQgcHkgPSBhc2NlbnQgKyB5OwogICAgbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICBmb3IgcnVuIGluICZsaW5lLnJlbmRlcl9kYXRhLnJ1bnMgewogICAgICAgIGxldCBjaGFyX3dpZHRoID0gcnVuLnNwYW4ud2lkdGg7CgogICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICBsZXQgcnVuX3ggPSBweDsKICAgICAgICBnbHlwaHMuY2xlYXIoKTsKICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAvLyBsZXQgeCA9IHB4ICsgZ2x5cGgueDsKICAgICAgICAgICAgLy8gbGV0IHkgPSBweSAtIGdseXBoLnk7CiAgICAgICAgICAgIGxldCB4ID0gcHg7CiAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgIC8vIHB4ICs9IGdseXBoLmFkdmFuY2UKICAgICAgICAgICAgcHggKz0gZ2x5cGguc2ltcGxlX2RhdGEoKS4xICogY2hhcl93aWR0aDsKICAgICAgICAgICAgZ2x5cGhzLnB1c2goR2x5cGggewogICAgICAgICAgICAgICAgaWQ6IGdseXBoLnNpbXBsZV9kYXRhKCkuMCwKICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICB5LAogICAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgbGV0IGNvbG9yID0gcnVuLnNwYW4uY29sb3I7CgogICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgICAgICBmb250X3NpemU6IHJ1bi5zaXplLAogICAgICAgICAgICBjb2xvciwKICAgICAgICAgICAgY3Vyc29yOiBydW4uc3Bhbi5jdXJzb3IsCiAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IE5vbmUsCiAgICAgICAgICAgIGJhc2VsaW5lOiBweSwKICAgICAgICAgICAgdG9wbGluZTogcHkgLSBhc2NlbnQsCiAgICAgICAgICAgIGxpbmVfaGVpZ2h0LAogICAgICAgICAgICBhZHZhbmNlOiBweCAtIHJ1bl94LAogICAgICAgICAgICBkZWNvcmF0aW9uOiBOb25lLAogICAgICAgICAgICBkZWNvcmF0aW9uX2NvbG9yOiBOb25lLAogICAgICAgIH07CgogICAgICAgIGlmIHN0eWxlLmFkdmFuY2UgPiAwLiAmJiBsaW5lX2hlaWdodCA+IDAuIHsKICAgICAgICAgICAgZGltZW5zaW9uLndpZHRoID0gc3R5bGUuYWR2YW5jZS5yb3VuZCgpOwogICAgICAgICAgICBkaW1lbnNpb24uaGVpZ2h0ID0gbGluZV9oZWlnaHQucm91bmQoKTsKICAgICAgICB9CgogICAgICAgIGlmIGZvbnQgIT0gY3VycmVudF9mb250IHx8IHN0eWxlLmZvbnRfc2l6ZSAhPSBjdXJyZW50X2ZvbnRfc2l6ZSB7CiAgICAgICAgICAgIGN1cnJlbnRfZm9udCA9IGZvbnQ7CiAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplID0gc3R5bGUuZm9udF9zaXplOwoKICAgICAgICAgICAgc2Vzc2lvbiA9IGdseXBoc19jYWNoZS5zZXNzaW9uKAogICAgICAgICAgICAgICAgaW1hZ2VfY2FjaGUsCiAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgICAgICAgICBmb250X2xpYnJhcnksCiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgICAgICAgICApOwogICAgICAgIH0KCiAgICAgICAgY29tcC5kcmF3X3J1bigKICAgICAgICAgICAgJm11dCBzZXNzaW9uLAogICAgICAgICAgICBSZWN0OjpuZXcocnVuX3gsIHB5LCBzdHlsZS5hZHZhbmNlLCAxLiksCiAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgJnN0eWxlLAogICAgICAgICAgICAmZ2x5cGhzLAogICAgICAgICk7CiAgICB9CgogICAgZGltZW5zaW9uCn0KCiNbaW5saW5lXQpmbiBuZXh0X2NvcHlfYnVmZmVyX3NpemUoc2l6ZTogdTY0KSAtPiB1NjQgewogICAgbGV0IGFsaWduX21hc2sgPSB3Z3B1OjpDT1BZX0JVRkZFUl9BTElHTk1FTlQgLSAxOwogICAgKChzaXplLm5leHRfcG93ZXJfb2ZfdHdvKCkgKyBhbGlnbl9tYXNrKSAmICFhbGlnbl9tYXNrKQogICAgICAgIC5tYXgod2dwdTo6Q09QWV9CVUZGRVJfQUxJR05NRU5UKQp9CgAAAAAAAAAAU1YAAAAAAAAAAAAAAAAAAAAAAABTVgAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADcQQAAAAAAANxBAAAAAAAAAAAAAAAA8L8" + ] + ] + }, + { + "file": "/Users/rapha/Documents/a/rio/pkgRio.nix", + "settings": + { + "buffer_size": 2578, + "encoding": "UTF-8", + "line_ending": "Unix" + }, + "undo_stack": + [ + [ + 4, + 1, + "cut", + null, + "AQAAAEkFAAAAAAAASQUAAAAAAAAVAAAAICAgIGRvQ2hlY2sgPSBmYWxzZTsK", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABdBQAAAAAAAF0FAAAAAAAAAAAAAAAA8L8" + ], + [ + 5, + 1, + "left_delete", + null, + "AQAAAEgFAAAAAAAASAUAAAAAAAABAAAACg", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABJBQAAAAAAAEkFAAAAAAAAAAAAAAAA8L8" + ] + ] + }, + { + "contents": "use raw_window_handle::{HasDisplayHandle, HasWindowHandle};\nuse rio_window::application::ApplicationHandler;\nuse rio_window::event_loop::ControlFlow;\nuse rio_window::event_loop::{ActiveEventLoop, DeviceEvents};\nuse rio_window::window::{Window, WindowId};\nuse rio_window::{\n dpi::LogicalSize, event::WindowEvent, event_loop::EventLoop, window::WindowAttributes,\n};\nuse std::error::Error;\nuse sugarloaf::{\n layout::RootStyle, FragmentStyle, FragmentStyleDecoration, Object, RichText,\n Sugarloaf, SugarCursor, SugarloafWindow, SugarloafWindowSize, UnderlineInfo, UnderlineShape,\n};\n\nfn main() {\n let width = 600.0;\n let height = 400.0;\n let window_event_loop = rio_window::event_loop::EventLoop::new().unwrap();\n let mut application = Application::new(&window_event_loop, width, height);\n let _ = application.run(window_event_loop);\n}\n\nstruct Application {\n sugarloaf: Option>,\n window: Option,\n height: f32,\n width: f32,\n}\n\nimpl Application {\n fn new(event_loop: &EventLoop<()>, width: f32, height: f32) -> Self {\n event_loop.listen_device_events(DeviceEvents::Never);\n\n Application {\n sugarloaf: None,\n window: None,\n width,\n height,\n }\n }\n\n fn run(&mut self, event_loop: EventLoop<()>) -> Result<(), Box> {\n let result = event_loop.run_app(self);\n result.map_err(Into::into)\n }\n}\n\nimpl ApplicationHandler for Application {\n fn resumed(&mut self, active_event_loop: &ActiveEventLoop) {\n let window_attribute = WindowAttributes::default()\n .with_title(\"Line height example\")\n .with_inner_size(LogicalSize::new(self.width, self.height))\n .with_resizable(true);\n let window = active_event_loop.create_window(window_attribute).unwrap();\n\n let scale_factor = window.scale_factor();\n let font_size = 24.;\n\n let line_height = 2.0;\n let sugarloaf_layout =\n RootStyle::new(scale_factor as f32, font_size, line_height);\n\n let size = window.inner_size();\n let sugarloaf_window = SugarloafWindow {\n handle: window.window_handle().unwrap().into(),\n display: window.display_handle().unwrap().into(),\n scale: scale_factor as f32,\n size: SugarloafWindowSize {\n width: size.width as f32,\n height: size.height as f32,\n },\n };\n\n let mut sugarloaf = Sugarloaf::new(\n sugarloaf_window,\n sugarloaf::SugarloafRenderer::default(),\n &sugarloaf::font::FontLibrary::default(),\n sugarloaf_layout,\n )\n .expect(\"Sugarloaf instance should be created\");\n\n sugarloaf.set_background_color(Some(wgpu::Color::RED));\n sugarloaf.create_rich_text();\n window.request_redraw();\n\n self.sugarloaf = Some(sugarloaf);\n self.window = Some(window);\n }\n\n fn window_event(\n &mut self,\n event_loop: &ActiveEventLoop,\n _window_id: WindowId,\n event: WindowEvent,\n ) {\n if self.sugarloaf.is_none() || self.window.is_none() {\n return;\n }\n\n let sugarloaf = self.sugarloaf.as_mut().unwrap();\n let window = self.window.as_mut().unwrap();\n\n match event {\n WindowEvent::CloseRequested => event_loop.exit(),\n WindowEvent::ScaleFactorChanged {\n // mut inner_size_writer,\n scale_factor,\n ..\n } => {\n let scale_factor_f32 = scale_factor as f32;\n let new_inner_size = window.inner_size();\n sugarloaf.rescale(scale_factor_f32);\n sugarloaf.resize(new_inner_size.width, new_inner_size.height);\n window.request_redraw();\n }\n WindowEvent::Resized(new_size) => {\n sugarloaf.resize(new_size.width, new_size.height);\n window.request_redraw();\n }\n WindowEvent::RedrawRequested { .. } => {\n let content = sugarloaf.content();\n content.sel(0).clear();\n content\n .new_line()\n .add_text(\n \"Sugarloaf\",\n FragmentStyle {\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .new_line()\n .add_text(\n \"│㏑¼\",\n FragmentStyle {\n color: [0.0, 0.0, 0.0, 1.0],\n background_color: Some([1.0, 1.0, 1.0, 1.0]),\n width: 2.0,\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"🥶\",\n FragmentStyle {\n color: [1.0, 0.0, 1.0, 1.0],\n background_color: Some([0.3, 0.5, 1.0, 1.0]),\n width: 2.0,\n ..FragmentStyle::default()\n },\n )\n .new_line()\n .add_text(\n \"│regular -> \",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Regular,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \" \",\n FragmentStyle {\n decoration: None,\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"|still|\",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Regular,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \" \",\n FragmentStyle {\n decoration: None,\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"│curly\",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Curly,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .new_line()\n .add_text(\n \"│dashed\",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Dashed,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \" \",\n FragmentStyle {\n decoration: None,\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"dotted\",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Dotted,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .new_line()\n .add_text(\n \"│ \\u{E0B6}Hello There!\\u{e0b4}\",\n FragmentStyle {\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.5, 0.5, 1.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"?\",\n FragmentStyle {\n color: [0.5, 0.5, 1.0, 1.0],\n background_color: Some([1.0, 1.0, 1.0, 1.0]),\n cursor: Some(SugarCursor::Block([1.0, 1.0, 1.0, 1.0])),\n ..FragmentStyle::default()\n },\n )\n .build();\n\n sugarloaf.set_objects(vec![Object::RichText(RichText {\n id: 0,\n position: [10., 0.],\n })]);\n sugarloaf.render();\n event_loop.set_control_flow(ControlFlow::Wait);\n }\n _ => (),\n }\n }\n}\n", + "file": "/Users/rapha/Documents/a/rio/sugarloaf/examples/line_height.rs", + "file_size": 11526, + "file_write_time": 133789560807006437, + "settings": + { + "buffer_size": 11510, + "line_ending": "Unix" + }, + "undo_stack": + [ + [ + 5, + 1, + "insert", + { + "characters": "\n" + }, + "AgAAAOwpAAAAAAAA7SkAAAAAAAAAAAAA7SkAAAAAAAABKgAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADsKQAAAAAAAOwpAAAAAAAAAAAAAAAA8L8" + ], + [ + 6, + 1, + "paste", + null, + "AQAAAAEqAAAAAAAAWCsAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAABKgAAAAAAAAEqAAAAAAAAAAAAAAAA8L8" + ], + [ + 11, + 1, + "left_delete", + null, + "AQAAACUqAAAAAAAAJSoAAAAAAAAgAAAA4pSCIFx1e0UwQjZ9SGVsbG8gVGhlcmUhXHV7ZTBiNH0", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlKgAAAAAAAEMqAAAAAAAAAAAAAAAA8L8" + ], + [ + 12, + 1, + "insert", + { + "characters": "?" + }, + "AQAAACUqAAAAAAAAJioAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlKgAAAAAAACUqAAAAAAAAAAAAAAAA8L8" + ], + [ + 24, + 1, + "paste", + null, + "AQAAAL0qAAAAAAAA0ioAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAC9KgAAAAAAAL0qAAAAAAAAAAAAAAAA8L8" + ], + [ + 34, + 1, + "left_delete", + null, + "AQAAANIqAAAAAAAA0ioAAAAAAAAUAAAAWzAuNSwgMC41LCAxLjAsIDEuMF0", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADSKgAAAAAAAOYqAAAAAAAAAAAAAAAA8L8" + ], + [ + 40, + 1, + "left_delete", + null, + "AQAAAHQqAAAAAAAAdCoAAAAAAAAUAAAAWzEuMCwgMS4wLCAxLjAsIDEuMF0", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACIKgAAAAAAAHQqAAAAAAAAAAAAAAAA8L8" + ], + [ + 41, + 1, + "paste", + null, + "AQAAAHQqAAAAAAAAiCoAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB0KgAAAAAAAHQqAAAAAAAAAAAAAAAA8L8" + ], + [ + 45, + 1, + "insert", + { + "characters": "\ncu" + }, + "BAAAANQqAAAAAAAA1SoAAAAAAAAAAAAA1SoAAAAAAADxKgAAAAAAAAAAAADxKgAAAAAAAPIqAAAAAAAAAAAAAPIqAAAAAAAA8yoAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADUKgAAAAAAANQqAAAAAAAA////////738" + ], + [ + 46, + 2, + "left_delete", + null, + "AgAAAPIqAAAAAAAA8ioAAAAAAAABAAAAdfEqAAAAAAAA8SoAAAAAAAABAAAAYw", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADzKgAAAAAAAPMqAAAAAAAAAAAAAAAA8L8" + ], + [ + 52, + 1, + "paste", + null, + "AQAAAPEqAAAAAAAAdCwAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADxKgAAAAAAAPEqAAAAAAAAAAAAAAAA8L8" + ], + [ + 64, + 2, + "left_delete", + null, + "AgAAAPIqAAAAAAAA8ioAAAAAAAAKAAAAZGVjb3JhdGlvbvEqAAAAAAAA8SoAAAAAAAABAAAAIA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADyKgAAAAAAAPwqAAAAAAAAAAAAAAAA8L8" + ], + [ + 65, + 1, + "insert", + { + "characters": "cursor" + }, + "BgAAAPEqAAAAAAAA8ioAAAAAAAAAAAAA8ioAAAAAAADzKgAAAAAAAAAAAADzKgAAAAAAAPQqAAAAAAAAAAAAAPQqAAAAAAAA9SoAAAAAAAAAAAAA9SoAAAAAAAD2KgAAAAAAAAAAAAD2KgAAAAAAAPcqAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADxKgAAAAAAAPEqAAAAAAAAAAAAAAAA8L8" + ], + [ + 69, + 1, + "left_delete", + null, + "AQAAAP4qAAAAAAAA/ioAAAAAAAAXAAAARnJhZ21lbnRTdHlsZURlY29yYXRpb24", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAD+KgAAAAAAABUrAAAAAAAAAAAAAAAA8L8" + ], + [ + 70, + 1, + "paste", + null, + "AQAAAP4qAAAAAAAACSsAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAD+KgAAAAAAAP4qAAAAAAAAAAAAAAAA8L8" + ], + [ + 73, + 1, + "left_delete", + null, + "AQAAAAsrAAAAAAAACysAAAAAAAAJAAAAVW5kZXJsaW5l", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAUKwAAAAAAAAsrAAAAAAAAAAAAAAAA8L8" + ], + [ + 74, + 1, + "insert", + { + "characters": "Block" + }, + "BQAAAAsrAAAAAAAADCsAAAAAAAAAAAAADCsAAAAAAAANKwAAAAAAAAAAAAANKwAAAAAAAA4rAAAAAAAAAAAAAA4rAAAAAAAADysAAAAAAAAAAAAADysAAAAAAAAQKwAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAALKwAAAAAAAAsrAAAAAAAAAAAAAAAA8L8" + ], + [ + 84, + 1, + "paste", + null, + "AQAAABErAAAAAAAAJSsAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAARKwAAAAAAABErAAAAAAAAAAAAAAAIiEA" + ], + [ + 85, + 1, + "insert", + { + "characters": ")," + }, + "AgAAACUrAAAAAAAAJisAAAAAAAAAAAAAJisAAAAAAAAnKwAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlKwAAAAAAACUrAAAAAAAAAAAAAAAA8L8" + ], + [ + 87, + 7, + "cut", + null, + "BwAAACgrAAAAAAAAKCsAAAAAAAAwAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVbmRlcmxpbmVJbmZvIHsKKCsAAAAAAAAoKwAAAAAAADIAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IC0yLjAsCigrAAAAAAAAKCsAAAAAAAAvAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogMS4wLAooKwAAAAAAACgrAAAAAAAANwAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzX2RvdWJsZWQ6IGZhbHNlLAooKwAAAAAAACgrAAAAAAAAQwAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlOiBVbmRlcmxpbmVTaGFwZTo6RG90dGVkLAooKwAAAAAAACgrAAAAAAAAIwAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKKCsAAAAAAAAoKwAAAAAAACAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSksCg", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABXKwAAAAAAAFcrAAAAAAAAAAAAAADIi0A" + ], + [ + 91, + 1, + "left_delete", + null, + "AQAAANEqAAAAAAAA0SoAAAAAAAABAAAALA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADSKgAAAAAAANIqAAAAAAAAAAAAAAAA8L8" + ], + [ + 95, + 1, + "insert", + { + "characters": ")" + }, + "AQAAACUrAAAAAAAAJisAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlKwAAAAAAACUrAAAAAAAAAAAAAAAA8L8" + ], + [ + 103, + 1, + "insert", + { + "characters": " Sug" + }, + "BAAAAPYBAAAAAAAA9wEAAAAAAAAAAAAA9wEAAAAAAAD4AQAAAAAAAAAAAAD4AQAAAAAAAPkBAAAAAAAAAAAAAPkBAAAAAAAA+gEAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAD2AQAAAAAAAPYBAAAAAAAAAAAAAAAA8L8" + ], + [ + 106, + 1, + "insert_completion", + { + "completion": "SugarCursor", + "format": "text", + "keep_prefix": false, + "must_insert": false, + "trigger": "SugarCursor" + }, + "AgAAAPcBAAAAAAAA9wEAAAAAAAADAAAAU3Vn9wEAAAAAAAACAgAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAD6AQAAAAAAAPoBAAAAAAAAAAAAAAAA8L8" + ], + [ + 107, + 1, + "insert", + { + "characters": "," + }, + "AQAAAAICAAAAAAAAAwIAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAACAgAAAAAAAAICAAAAAAAAAAAAAAAA8L8" + ] + ] + }, + { + "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/content.rs", + "settings": + { + "buffer_size": 19461, + "line_ending": "Unix" + }, + "undo_stack": + [ + [ + 15, + 1, + "insert", + { + "characters": " *" + }, + "AgAAAGUjAAAAAAAAZiMAAAAAAAAAAAAAZiMAAAAAAABnIwAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABlIwAAAAAAAGUjAAAAAAAAAAAAAAAA8L8" + ], + [ + 16, + 1, + "insert", + { + "characters": " " + }, + "AQAAAGcjAAAAAAAAaCMAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABnIwAAAAAAAGcjAAAAAAAAAAAAAAAA8L8" + ], + [ + 17, + 1, + "paste", + null, + "AQAAAGgjAAAAAAAAciMAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABoIwAAAAAAAGgjAAAAAAAAAAAAAAAA8L8" + ], + [ + 18, + 1, + "insert", + { + "characters": ".di" + }, + "AwAAAHIjAAAAAAAAcyMAAAAAAAAAAAAAcyMAAAAAAAB0IwAAAAAAAAAAAAB0IwAAAAAAAHUjAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAByIwAAAAAAAHIjAAAAAAAAAAAAAAAA8L8" + ], + [ + 19, + 1, + "insert_completion", + { + "completion": "dimensions", + "format": "text", + "keep_prefix": false, + "must_insert": false, + "trigger": "dimensions" + }, + "AgAAAHMjAAAAAAAAcyMAAAAAAAACAAAAZGlzIwAAAAAAAH0jAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB1IwAAAAAAAHUjAAAAAAAAAAAAAAAA8L8" + ], + [ + 20, + 1, + "insert", + { + "characters": ".line" + }, + "BQAAAH0jAAAAAAAAfiMAAAAAAAAAAAAAfiMAAAAAAAB/IwAAAAAAAAAAAAB/IwAAAAAAAIAjAAAAAAAAAAAAAIAjAAAAAAAAgSMAAAAAAAAAAAAAgSMAAAAAAACCIwAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB9IwAAAAAAAH0jAAAAAAAAAAAAAAAA8L8" + ], + [ + 23, + 1, + "insert_completion", + { + "completion": "line_height", + "format": "text", + "keep_prefix": false, + "must_insert": false, + "trigger": "line_height" + }, + "AgAAAH4jAAAAAAAAfiMAAAAAAAAEAAAAbGluZX4jAAAAAAAAiSMAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACCIwAAAAAAAIIjAAAAAAAAAAAAAAAA8L8" + ], + [ + 26, + 1, + "left_delete", + null, + "AQAAAHMjAAAAAAAAcyMAAAAAAAALAAAAZGltZW5zaW9ucy4", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB+IwAAAAAAAHMjAAAAAAAAAAAAAAAA8L8" + ], + [ + 43, + 1, + "revert", + null, + "AwAAAAAAAAAAAAAAAAAAAAAAAAAeTAAALy8gQ29weXJpZ2h0IChjKSAyMDIzLXByZXNlbnQsIFJhcGhhZWwgQW1vcmltLgovLwovLyBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGUKLy8gTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLgoKdXNlIGNyYXRlOjpjb21wb25lbnRzOjpyaWNoX3RleHQ6OlJpY2hUZXh0QnJ1c2g7CnVzZSBjcmF0ZTo6Zm9udDo6Rm9udExpYnJhcnk7CnVzZSBjcmF0ZTo6Zm9udF9pbnRyb3NwZWN0b3I6OnNoYXBlOjpjbHVzdGVyOjpHbHlwaENsdXN0ZXI7CnVzZSBjcmF0ZTo6Zm9udF9pbnRyb3NwZWN0b3I6OnNoYXBlOjpjbHVzdGVyOjpPd25lZEdseXBoQ2x1c3RlcjsKdXNlIGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6c2hhcGU6OlNoYXBlQ29udGV4dDsKdXNlIGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6dGV4dDo6U2NyaXB0Owp1c2UgY3JhdGU6OmZvbnRfaW50cm9zcGVjdG9yOjpNZXRyaWNzOwp1c2UgY3JhdGU6OmxheW91dDo6cmVuZGVyX2RhdGE6OlJlbmRlckRhdGE7CnVzZSBjcmF0ZTo6bGF5b3V0OjpSaWNoVGV4dExheW91dDsKdXNlIGxydTo6THJ1Q2FjaGU7CnVzZSBydXN0Y19oYXNoOjpGeEhhc2hNYXA7CnVzZSBzdGQ6Om51bTo6Tm9uWmVyb1VzaXplOwoKdXNlIGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6QXR0cmlidXRlczsKdXNlIGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6U2V0dGluZzsKdXNlIGNyYXRlOjp7c3VnYXJsb2FmOjpwcmltaXRpdmVzOjpTdWdhckN1cnNvciwgR3JhcGhpY307CgovLy8gRGF0YSB0aGF0IGRlc2NyaWJlcyBhIGZyYWdtZW50LgojW2Rlcml2ZShEZWJ1ZywgQ2xvbmUpXQpwdWIgc3RydWN0IEZyYWdtZW50RGF0YSB7CiAgICBwdWIgY29udGVudDogU3RyaW5nLAogICAgLy8vIFN0eWxlCiAgICBwdWIgc3R5bGU6IEZyYWdtZW50U3R5bGUsCn0KCiNbZGVyaXZlKERlZmF1bHQsIENsb25lKV0KcHViIHN0cnVjdCBCdWlsZGVyTGluZSB7CiAgICAvLy8gQ29sbGVjdGlvbiBvZiBmcmFnbWVudHMuCiAgICBwdWIgZnJhZ21lbnRzOiBWZWM8RnJhZ21lbnREYXRhPiwKICAgIHB1YiByZW5kZXJfZGF0YTogUmVuZGVyRGF0YSwKfQoKLy8vIEJ1aWxkZXIgc3RhdGUuCiNbZGVyaXZlKERlZmF1bHQpXQpwdWIgc3RydWN0IEJ1aWxkZXJTdGF0ZSB7CiAgICAvLy8gTGluZXMgU3RhdGUKICAgIHB1YiBsaW5lczogVmVjPEJ1aWxkZXJMaW5lPiwKICAgIC8vLyBGb250IHZhcmlhdGlvbiBzZXR0aW5nIGNhY2hlLgogICAgcHViIHZhcnM6IEZvbnRTZXR0aW5nQ2FjaGU8ZjMyPiwKICAgIG1ldHJpY3NfY2FjaGU6IE1ldHJpY3NDYWNoZSwKICAgIHNjYWxlZF9mb250X3NpemU6IGYzMiwKICAgIHB1YiBsYXlvdXQ6IFJpY2hUZXh0TGF5b3V0LAp9CgppbXBsIEJ1aWxkZXJTdGF0ZSB7CiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBmcm9tX2xheW91dChsYXlvdXQ6ICZSaWNoVGV4dExheW91dCkgLT4gU2VsZiB7CiAgICAgICAgU2VsZiB7CiAgICAgICAgICAgIGxheW91dDogKmxheW91dCwKICAgICAgICAgICAgc2NhbGVkX2ZvbnRfc2l6ZTogbGF5b3V0LmZvbnRfc2l6ZSAqIGxheW91dC5kaW1lbnNpb25zLnNjYWxlLAogICAgICAgICAgICAuLkJ1aWxkZXJTdGF0ZTo6ZGVmYXVsdCgpCiAgICAgICAgfQogICAgfQogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gbmV3X2xpbmUoJm11dCBzZWxmKSB7CiAgICAgICAgc2VsZi5saW5lcy5wdXNoKEJ1aWxkZXJMaW5lOjpkZWZhdWx0KCkpOwogICAgfQogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gY3VycmVudF9saW5lKCZzZWxmKSAtPiB1c2l6ZSB7CiAgICAgICAgc2VsZi5saW5lcy5sZW4oKS53cmFwcGluZ19zdWIoMSkKICAgIH0KICAgICNbaW5saW5lXQogICAgcHViIGZuIGNsZWFyKCZtdXQgc2VsZikgewogICAgICAgIHNlbGYubGluZXMuY2xlYXIoKTsKICAgICAgICBzZWxmLnZhcnMuY2xlYXIoKTsKICAgIH0KICAgICNbaW5saW5lXQogICAgcHViIGZuIHJlc2NhbGUoJm11dCBzZWxmLCBzY2FsZV9mYWN0b3I6IGYzMikgewogICAgICAgIHNlbGYubWV0cmljc19jYWNoZS5pbm5lci5jbGVhcigpOwogICAgICAgIHNlbGYuc2NhbGVkX2ZvbnRfc2l6ZSA9IHNlbGYubGF5b3V0LmZvbnRfc2l6ZSAqIHNjYWxlX2ZhY3RvcjsKICAgICAgICBzZWxmLmxheW91dC5yZXNjYWxlKHNjYWxlX2ZhY3Rvcik7CiAgICB9CiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBiZWdpbigmbXV0IHNlbGYpIHsKICAgICAgICBzZWxmLmxpbmVzLnB1c2goQnVpbGRlckxpbmU6OmRlZmF1bHQoKSk7CiAgICB9CiAgICAjW2lubGluZV0KICAgIHB1YiBmbiB1cGRhdGVfZm9udF9zaXplKCZtdXQgc2VsZikgewogICAgICAgIGxldCBmb250X3NpemUgPSBzZWxmLmxheW91dC5mb250X3NpemU7CiAgICAgICAgbGV0IHNjYWxlID0gc2VsZi5sYXlvdXQuZGltZW5zaW9ucy5zY2FsZTsKICAgICAgICBsZXQgcHJldl9mb250X3NpemUgPSBzZWxmLnNjYWxlZF9mb250X3NpemU7CiAgICAgICAgc2VsZi5zY2FsZWRfZm9udF9zaXplID0gZm9udF9zaXplICogc2NhbGU7CgogICAgICAgIGlmIHByZXZfZm9udF9zaXplICE9IHNlbGYuc2NhbGVkX2ZvbnRfc2l6ZSB7CiAgICAgICAgICAgIHNlbGYubWV0cmljc19jYWNoZS5pbm5lci5jbGVhcigpOwogICAgICAgIH0KICAgIH0KCiAgICBwdWIgZm4gaW5jcmVhc2VfZm9udF9zaXplKCZtdXQgc2VsZikgLT4gYm9vbCB7CiAgICAgICAgaWYgc2VsZi5sYXlvdXQuZm9udF9zaXplIDwgNDAuMCB7CiAgICAgICAgICAgIHNlbGYubGF5b3V0LmZvbnRfc2l6ZSArPSAxLjA7CiAgICAgICAgICAgIHNlbGYudXBkYXRlX2ZvbnRfc2l6ZSgpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgZmFsc2UKICAgIH0KCiAgICBwdWIgZm4gZGVjcmVhc2VfZm9udF9zaXplKCZtdXQgc2VsZikgLT4gYm9vbCB7CiAgICAgICAgaWYgc2VsZi5sYXlvdXQuZm9udF9zaXplID4gNi4wIHsKICAgICAgICAgICAgc2VsZi5sYXlvdXQuZm9udF9zaXplIC09IDEuMDsKICAgICAgICAgICAgc2VsZi51cGRhdGVfZm9udF9zaXplKCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBmYWxzZQogICAgfQoKICAgIHB1YiBmbiByZXNldF9mb250X3NpemUoJm11dCBzZWxmKSAtPiBib29sIHsKICAgICAgICBpZiBzZWxmLmxheW91dC5mb250X3NpemUgIT0gc2VsZi5sYXlvdXQub3JpZ2luYWxfZm9udF9zaXplIHsKICAgICAgICAgICAgc2VsZi5sYXlvdXQuZm9udF9zaXplID0gc2VsZi5sYXlvdXQub3JpZ2luYWxfZm9udF9zaXplOwogICAgICAgICAgICBzZWxmLnVwZGF0ZV9mb250X3NpemUoKTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGZhbHNlCiAgICB9Cn0KCi8vLyBJbmRleCBpbnRvIGEgZm9udCBzZXR0aW5nIGNhY2hlLgpwdWIgdHlwZSBGb250U2V0dGluZ0tleSA9IHUzMjsKCi8vLyBDYWNoZSBvZiB0YWcvdmFsdWUgcGFpcnMgZm9yIGZvbnQgc2V0dGluZ3MuCiNbZGVyaXZlKERlZmF1bHQpXQpwdWIgc3RydWN0IEZvbnRTZXR0aW5nQ2FjaGU8VDogQ29weSArIFBhcnRpYWxPcmQgKyBQYXJ0aWFsRXE+IHsKICAgIHNldHRpbmdzOiBWZWM8U2V0dGluZzxUPj4sCiAgICBsaXN0czogVmVjPEZvbnRTZXR0aW5nTGlzdD4sCiAgICB0bXA6IFZlYzxTZXR0aW5nPFQ+PiwKfQoKaW1wbDxUOiBDb3B5ICsgUGFydGlhbE9yZCArIFBhcnRpYWxFcT4gRm9udFNldHRpbmdDYWNoZTxUPiB7CiAgICBwdWIgZm4gZ2V0KCZzZWxmLCBrZXk6IHUzMikgLT4gJltTZXR0aW5nPFQ+XSB7CiAgICAgICAgaWYga2V5ID09ICEwIHsKICAgICAgICAgICAgJltdCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2VsZi5saXN0cwogICAgICAgICAgICAgICAgLmdldChrZXkgYXMgdXNpemUpCiAgICAgICAgICAgICAgICAubWFwKHxsaXN0fCBsaXN0LmdldCgmc2VsZi5zZXR0aW5ncykpCiAgICAgICAgICAgICAgICAudW53cmFwX29yKCZbXSkKICAgICAgICB9CiAgICB9CgogICAgcHViIGZuIGNsZWFyKCZtdXQgc2VsZikgewogICAgICAgIHNlbGYuc2V0dGluZ3MuY2xlYXIoKTsKICAgICAgICBzZWxmLmxpc3RzLmNsZWFyKCk7CiAgICAgICAgc2VsZi50bXAuY2xlYXIoKTsKICAgIH0KfQoKLy8vIFNlbnRpbmVsIGZvciBhbiBlbXB0eSBzZXQgb2YgZm9udCBzZXR0aW5ncy4KcHViIGNvbnN0IEVNUFRZX0ZPTlRfU0VUVElOR1M6IEZvbnRTZXR0aW5nS2V5ID0gITA7CgovLy8gUmFuZ2Ugd2l0aGluIGEgZm9udCBzZXR0aW5nIGNhY2hlLgojW2Rlcml2ZShDb3B5LCBDbG9uZSldCnN0cnVjdCBGb250U2V0dGluZ0xpc3QgewogICAgcHViIHN0YXJ0OiB1MzIsCiAgICBwdWIgZW5kOiB1MzIsCn0KCmltcGwgRm9udFNldHRpbmdMaXN0IHsKICAgIHB1YiBmbiBnZXQ8VD4oc2VsZiwgZWxlbWVudHM6ICZbVF0pIC0+ICZbVF0gewogICAgICAgIGVsZW1lbnRzCiAgICAgICAgICAgIC5nZXQoc2VsZi5zdGFydCBhcyB1c2l6ZS4uc2VsZi5lbmQgYXMgdXNpemUpCiAgICAgICAgICAgIC51bndyYXBfb3IoJltdKQogICAgfQp9CgojW3JlcHIodTgpXQojW2Rlcml2ZShDb3B5LCBDbG9uZSwgUGFydGlhbEVxLCBEZWJ1ZywgRGVmYXVsdCldCnB1YiBlbnVtIFVuZGVybGluZVNoYXBlIHsKICAgICNbZGVmYXVsdF0KICAgIFJlZ3VsYXIgPSAwLAogICAgRG90dGVkID0gMSwKICAgIERhc2hlZCA9IDIsCiAgICBDdXJseSA9IDMsCn0KCiNbZGVyaXZlKENvcHksIENsb25lLCBQYXJ0aWFsRXEsIERlYnVnKV0KcHViIHN0cnVjdCBVbmRlcmxpbmVJbmZvIHsKICAgIHB1YiBvZmZzZXQ6IGYzMiwKICAgIHB1YiBzaXplOiBmMzIsCiAgICBwdWIgaXNfZG91YmxlZDogYm9vbCwKICAgIHB1YiBzaGFwZTogVW5kZXJsaW5lU2hhcGUsCn0KCiNbZGVyaXZlKENvcHksIENsb25lLCBQYXJ0aWFsRXEsIERlYnVnKV0KcHViIGVudW0gRnJhZ21lbnRTdHlsZURlY29yYXRpb24gewogICAgLy8gb2Zmc2V0LCBzaXplCiAgICBVbmRlcmxpbmUoVW5kZXJsaW5lSW5mbyksCiAgICBTdHJpa2V0aHJvdWdoLAp9CgojW2Rlcml2ZShDb3B5LCBDbG9uZSwgUGFydGlhbEVxLCBEZWJ1ZyldCnB1YiBzdHJ1Y3QgRnJhZ21lbnRTdHlsZSB7CiAgICBwdWIgZm9udF9pZDogdXNpemUsCiAgICAvLyAgVW5pY29kZSB3aWR0aAogICAgcHViIHdpZHRoOiBmMzIsCiAgICAvLy8gRm9udCBhdHRyaWJ1dGVzLgogICAgcHViIGZvbnRfYXR0cnM6IEF0dHJpYnV0ZXMsCiAgICAvLy8gRm9udCBjb2xvci4KICAgIHB1YiBjb2xvcjogW2YzMjsgNF0sCiAgICAvLy8gQmFja2dyb3VuZCBjb2xvci4KICAgIHB1YiBiYWNrZ3JvdW5kX2NvbG9yOiBPcHRpb248W2YzMjsgNF0+LAogICAgLy8vIEZvbnQgdmFyaWF0aW9ucy4KICAgIHB1YiBmb250X3ZhcnM6IEZvbnRTZXR0aW5nS2V5LAogICAgLy8vIEFkZGl0aW9uYWwgc3BhY2luZyBiZXR3ZWVuIGxldHRlcnMgKGNsdXN0ZXJzKSBvZiB0ZXh0LgogICAgLy8gcHViIGxldHRlcl9zcGFjaW5nOiBmMzIsCiAgICAvLy8gQWRkaXRpb25hbCBzcGFjaW5nIGJldHdlZW4gd29yZHMgb2YgdGV4dC4KICAgIC8vIHB1YiB3b3JkX3NwYWNpbmc6IGYzMiwKICAgIC8vLyBNdWx0aXBsaWNhdGl2ZSBsaW5lIHNwYWNpbmcgZmFjdG9yLgogICAgLy8gcHViIGxpbmVfc3BhY2luZzogZjMyLAogICAgLy8vIEVuYWJsZSB1bmRlcmxpbmUgZGVjb3JhdGlvbi4KICAgIHB1YiBkZWNvcmF0aW9uOiBPcHRpb248RnJhZ21lbnRTdHlsZURlY29yYXRpb24+LAogICAgLy8vIERlY29yYXRpb24gY29sb3IuCiAgICBwdWIgZGVjb3JhdGlvbl9jb2xvcjogT3B0aW9uPFtmMzI7IDRdPiwKICAgIC8vLyBDdXJzb3Igc3R5bGUuCiAgICBwdWIgY3Vyc29yOiBPcHRpb248U3VnYXJDdXJzb3I+LAogICAgLy8vIE1lZGlhCiAgICBwdWIgbWVkaWE6IE9wdGlvbjxHcmFwaGljPiwKfQoKaW1wbCBEZWZhdWx0IGZvciBGcmFnbWVudFN0eWxlIHsKICAgIGZuIGRlZmF1bHQoKSAtPiBTZWxmIHsKICAgICAgICBTZWxmIHsKICAgICAgICAgICAgZm9udF9pZDogMCwKICAgICAgICAgICAgd2lkdGg6IDEuMCwKICAgICAgICAgICAgZm9udF9hdHRyczogQXR0cmlidXRlczo6ZGVmYXVsdCgpLAogICAgICAgICAgICBmb250X3ZhcnM6IEVNUFRZX0ZPTlRfU0VUVElOR1MsCiAgICAgICAgICAgIC8vIGxldHRlcl9zcGFjaW5nOiAwLiwKICAgICAgICAgICAgLy8gd29yZF9zcGFjaW5nOiAwLiwKICAgICAgICAgICAgLy8gbGluZV9zcGFjaW5nOiAxLiwKICAgICAgICAgICAgY29sb3I6IFsxLjAsIDEuMCwgMS4wLCAxLjBdLAogICAgICAgICAgICBiYWNrZ3JvdW5kX2NvbG9yOiBOb25lLAogICAgICAgICAgICBjdXJzb3I6IE5vbmUsCiAgICAgICAgICAgIGRlY29yYXRpb246IE5vbmUsCiAgICAgICAgICAgIGRlY29yYXRpb25fY29sb3I6IE5vbmUsCiAgICAgICAgICAgIG1lZGlhOiBOb25lLAogICAgICAgIH0KICAgIH0KfQoKLy8vIENvbnRleHQgZm9yIHBhcmFncmFwaCBsYXlvdXQuCnB1YiBzdHJ1Y3QgQ29udGVudCB7CiAgICBmb250czogRm9udExpYnJhcnksCiAgICBmb250X2ZlYXR1cmVzOiBWZWM8Y3JhdGU6OmZvbnRfaW50cm9zcGVjdG9yOjpTZXR0aW5nPHUxNj4+LAogICAgc2N4OiBTaGFwZUNvbnRleHQsCiAgICBwdWIgc3RhdGVzOiBGeEhhc2hNYXA8dXNpemUsIEJ1aWxkZXJTdGF0ZT4sCiAgICB3b3JkX2NhY2hlOiBXb3JkQ2FjaGUsCiAgICBzZWxlY3RvcjogT3B0aW9uPHVzaXplPiwKfQoKaW1wbCBDb250ZW50IHsKICAgIC8vLyBDcmVhdGVzIGEgbmV3IGxheW91dCBjb250ZXh0IHdpdGggdGhlIHNwZWNpZmllZCBmb250IGxpYnJhcnkuCiAgICBwdWIgZm4gbmV3KGZvbnRfbGlicmFyeTogJkZvbnRMaWJyYXJ5KSAtPiBTZWxmIHsKICAgICAgICBTZWxmIHsKICAgICAgICAgICAgZm9udHM6IGZvbnRfbGlicmFyeS5jbG9uZSgpLAogICAgICAgICAgICBzY3g6IFNoYXBlQ29udGV4dDo6bmV3KCksCiAgICAgICAgICAgIHN0YXRlczogRnhIYXNoTWFwOjpkZWZhdWx0KCksCiAgICAgICAgICAgIHdvcmRfY2FjaGU6IFdvcmRDYWNoZTo6bmV3KCksCiAgICAgICAgICAgIGZvbnRfZmVhdHVyZXM6IHZlYyFbXSwKICAgICAgICAgICAgc2VsZWN0b3I6IE5vbmUsCiAgICAgICAgfQogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHNlbCgmbXV0IHNlbGYsIHN0YXRlX2lkOiB1c2l6ZSkgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBzZWxmLnNlbGVjdG9yID0gU29tZShzdGF0ZV9pZCk7CgogICAgICAgIHNlbGYKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBmb250X2xpYnJhcnkoJnNlbGYpIC0+ICZGb250TGlicmFyeSB7CiAgICAgICAgJnNlbGYuZm9udHMKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBzZXRfZm9udF9saWJyYXJ5KCZtdXQgc2VsZiwgZm9udF9saWJyYXJ5OiAmRm9udExpYnJhcnkpIHsKICAgICAgICBzZWxmLmZvbnRzID0gZm9udF9saWJyYXJ5LmNsb25lKCk7CiAgICAgICAgc2VsZi53b3JkX2NhY2hlID0gV29yZENhY2hlOjpuZXcoKTsKICAgICAgICBmb3IgbGluZSBpbiBzZWxmLnN0YXRlcy52YWx1ZXNfbXV0KCkgewogICAgICAgICAgICBsaW5lLm1ldHJpY3NfY2FjaGUgPSBNZXRyaWNzQ2FjaGU6OmRlZmF1bHQoKTsKICAgICAgICB9CiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gZ2V0X3N0YXRlKCZzZWxmLCBzdGF0ZV9pZDogJnVzaXplKSAtPiBPcHRpb248JkJ1aWxkZXJTdGF0ZT4gewogICAgICAgIHNlbGYuc3RhdGVzLmdldChzdGF0ZV9pZCkKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBnZXRfc3RhdGVfbXV0KCZtdXQgc2VsZiwgc3RhdGVfaWQ6ICZ1c2l6ZSkgLT4gT3B0aW9uPCZtdXQgQnVpbGRlclN0YXRlPiB7CiAgICAgICAgc2VsZi5zdGF0ZXMuZ2V0X211dChzdGF0ZV9pZCkKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBzZXRfZm9udF9mZWF0dXJlcygKICAgICAgICAmbXV0IHNlbGYsCiAgICAgICAgZm9udF9mZWF0dXJlczogVmVjPGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6U2V0dGluZzx1MTY+PiwKICAgICkgewogICAgICAgIHNlbGYuZm9udF9mZWF0dXJlcyA9IGZvbnRfZmVhdHVyZXM7CiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gY3JlYXRlX3N0YXRlKCZtdXQgc2VsZiwgcmljaF90ZXh0X2xheW91dDogJlJpY2hUZXh0TGF5b3V0KSAtPiB1c2l6ZSB7CiAgICAgICAgbGV0IGlkID0gc2VsZi5zdGF0ZXMubGVuKCk7CiAgICAgICAgc2VsZi5zdGF0ZXMKICAgICAgICAgICAgLmluc2VydChpZCwgQnVpbGRlclN0YXRlOjpmcm9tX2xheW91dChyaWNoX3RleHRfbGF5b3V0KSk7CiAgICAgICAgaWQKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiB1cGRhdGVfZGltZW5zaW9ucygKICAgICAgICAmbXV0IHNlbGYsCiAgICAgICAgc3RhdGVfaWQ6ICZ1c2l6ZSwKICAgICAgICBhZHZhbmNlX2JydXNoOiAmbXV0IFJpY2hUZXh0QnJ1c2gsCiAgICApIHsKICAgICAgICBsZXQgbXV0IGNvbnRlbnQgPSBDb250ZW50OjpuZXcoJnNlbGYuZm9udHMpOwogICAgICAgIGlmIGxldCBTb21lKHJ0ZSkgPSBzZWxmLnN0YXRlcy5nZXRfbXV0KHN0YXRlX2lkKSB7CiAgICAgICAgICAgIGxldCBpZCA9IGNvbnRlbnQuY3JlYXRlX3N0YXRlKCZydGUubGF5b3V0KTsKICAgICAgICAgICAgY29udGVudAogICAgICAgICAgICAgICAgLnNlbChpZCkKICAgICAgICAgICAgICAgIC5uZXdfbGluZSgpCiAgICAgICAgICAgICAgICAuYWRkX3RleHQoIiAiLCBGcmFnbWVudFN0eWxlOjpkZWZhdWx0KCkpCiAgICAgICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICAgICAgbGV0IHJlbmRlcl9kYXRhID0gY29udGVudC5nZXRfc3RhdGUoJmlkKS51bndyYXAoKS5saW5lc1swXS5jbG9uZSgpOwoKICAgICAgICAgICAgaWYgbGV0IFNvbWUoZGltZW5zaW9uKSA9IGFkdmFuY2VfYnJ1c2guZGltZW5zaW9ucygmc2VsZi5mb250cywgJnJlbmRlcl9kYXRhKSB7CiAgICAgICAgICAgICAgICBydGUubGF5b3V0LmRpbWVuc2lvbnMuaGVpZ2h0ID0gZGltZW5zaW9uLmhlaWdodCAqIHJ0ZS5sYXlvdXQubGluZV9oZWlnaHQ7CiAgICAgICAgICAgICAgICBydGUubGF5b3V0LmRpbWVuc2lvbnMud2lkdGggPSBkaW1lbnNpb24ud2lkdGg7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gY2xlYXJfc3RhdGUoJm11dCBzZWxmLCBpZDogJnVzaXplKSB7CiAgICAgICAgaWYgbGV0IFNvbWUoc3RhdGUpID0gc2VsZi5zdGF0ZXMuZ2V0X211dChpZCkgewogICAgICAgICAgICBzdGF0ZS5jbGVhcigpOwogICAgICAgICAgICBzdGF0ZS5iZWdpbigpOwogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBuZXdfbGluZV93aXRoX2lkKCZtdXQgc2VsZiwgaWQ6ICZ1c2l6ZSkgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBpZiBsZXQgU29tZShjb250ZW50KSA9IHNlbGYuc3RhdGVzLmdldF9tdXQoaWQpIHsKICAgICAgICAgICAgY29udGVudC5uZXdfbGluZSgpOwogICAgICAgIH0KCiAgICAgICAgc2VsZgogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIG5ld19saW5lKCZtdXQgc2VsZikgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBpZiBsZXQgU29tZShzZWxlY3RvcikgPSBzZWxmLnNlbGVjdG9yIHsKICAgICAgICAgICAgcmV0dXJuIHNlbGYubmV3X2xpbmVfd2l0aF9pZCgmc2VsZWN0b3IpOwogICAgICAgIH0KCiAgICAgICAgc2VsZgogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIGNsZWFyX2xpbmUoJm11dCBzZWxmLCBsaW5lX3RvX2NsZWFyOiB1c2l6ZSkgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBpZiBsZXQgU29tZShzZWxlY3RvcikgPSBzZWxmLnNlbGVjdG9yIHsKICAgICAgICAgICAgaWYgbGV0IFNvbWUoc3RhdGUpID0gc2VsZi5zdGF0ZXMuZ2V0X211dCgmc2VsZWN0b3IpIHsKICAgICAgICAgICAgICAgIHN0YXRlLmxpbmVzW2xpbmVfdG9fY2xlYXJdLmZyYWdtZW50cy5jbGVhcigpOwogICAgICAgICAgICAgICAgc3RhdGUubGluZXNbbGluZV90b19jbGVhcl0ucmVuZGVyX2RhdGEuY2xlYXIoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgc2VsZgogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIGNsZWFyX3dpdGhfaWQoJm11dCBzZWxmLCBpZDogJnVzaXplKSAtPiAmbXV0IENvbnRlbnQgewogICAgICAgIGlmIGxldCBTb21lKHN0YXRlKSA9IHNlbGYuc3RhdGVzLmdldF9tdXQoaWQpIHsKICAgICAgICAgICAgc3RhdGUuY2xlYXIoKTsKICAgICAgICAgICAgc3RhdGUuYmVnaW4oKTsKICAgICAgICB9CgogICAgICAgIHNlbGYKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBjbGVhcl9hbGwoJm11dCBzZWxmKSAtPiAmbXV0IENvbnRlbnQgewogICAgICAgIGZvciBzdGF0ZSBpbiAmbXV0IHNlbGYuc3RhdGVzLnZhbHVlc19tdXQoKSB7CiAgICAgICAgICAgIHN0YXRlLmNsZWFyKCk7CiAgICAgICAgICAgIHN0YXRlLmJlZ2luKCk7CiAgICAgICAgfQoKICAgICAgICBzZWxmCiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gY2xlYXIoJm11dCBzZWxmKSAtPiAmbXV0IENvbnRlbnQgewogICAgICAgIGlmIGxldCBTb21lKHNlbGVjdG9yKSA9IHNlbGYuc2VsZWN0b3IgewogICAgICAgICAgICByZXR1cm4gc2VsZi5jbGVhcl93aXRoX2lkKCZzZWxlY3Rvcik7CiAgICAgICAgfQoKICAgICAgICBzZWxmCiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gYWRkX3RleHQoJm11dCBzZWxmLCB0ZXh0OiAmc3RyLCBzdHlsZTogRnJhZ21lbnRTdHlsZSkgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBpZiBsZXQgU29tZShzZWxlY3RvcikgPSBzZWxmLnNlbGVjdG9yIHsKICAgICAgICAgICAgcmV0dXJuIHNlbGYuYWRkX3RleHRfd2l0aF9pZCgmc2VsZWN0b3IsIHRleHQsIHN0eWxlKTsKICAgICAgICB9CgogICAgICAgIHNlbGYKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBhZGRfdGV4dF9vbl9saW5lKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBsaW5lOiB1c2l6ZSwKICAgICAgICB0ZXh0OiAmc3RyLAogICAgICAgIHN0eWxlOiBGcmFnbWVudFN0eWxlLAogICAgKSAtPiAmbXV0IENvbnRlbnQgewogICAgICAgIGlmIGxldCBTb21lKHNlbGVjdG9yKSA9IHNlbGYuc2VsZWN0b3IgewogICAgICAgICAgICBpZiBsZXQgU29tZShzdGF0ZSkgPSBzZWxmLnN0YXRlcy5nZXRfbXV0KCZzZWxlY3RvcikgewogICAgICAgICAgICAgICAgbGV0IGxpbmUgPSAmbXV0IHN0YXRlLmxpbmVzW2xpbmVdOwoKICAgICAgICAgICAgICAgIGxpbmUuZnJhZ21lbnRzLnB1c2goRnJhZ21lbnREYXRhIHsKICAgICAgICAgICAgICAgICAgICBjb250ZW50OiB0ZXh0LnRvX3N0cmluZygpLAogICAgICAgICAgICAgICAgICAgIHN0eWxlLAogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHNlbGYKICAgIH0KCiAgICAvLy8gQWRkcyBhIHRleHQgZnJhZ21lbnQgdG8gdGhlIHBhcmFncmFwaC4KICAgIHB1YiBmbiBhZGRfdGV4dF93aXRoX2lkKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBpZDogJnVzaXplLAogICAgICAgIHRleHQ6ICZzdHIsCiAgICAgICAgc3R5bGU6IEZyYWdtZW50U3R5bGUsCiAgICApIC0+ICZtdXQgQ29udGVudCB7CiAgICAgICAgaWYgbGV0IFNvbWUoc3RhdGUpID0gc2VsZi5zdGF0ZXMuZ2V0X211dChpZCkgewogICAgICAgICAgICBsZXQgY3VycmVudF9saW5lID0gc3RhdGUuY3VycmVudF9saW5lKCk7CiAgICAgICAgICAgIGlmIGxldCBTb21lKGxpbmUpID0gJm11dCBzdGF0ZS5saW5lcy5nZXRfbXV0KGN1cnJlbnRfbGluZSkgewogICAgICAgICAgICAgICAgbGluZS5mcmFnbWVudHMucHVzaChGcmFnbWVudERhdGEgewogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHRleHQudG9fc3RyaW5nKCksCiAgICAgICAgICAgICAgICAgICAgc3R5bGUsCiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgc2VsZgogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIGJ1aWxkKCZtdXQgc2VsZikgewogICAgICAgIGlmIGxldCBTb21lKHNlbGVjdG9yKSA9IHNlbGYuc2VsZWN0b3IgewogICAgICAgICAgICBpZiBsZXQgU29tZShzdGF0ZSkgPSBzZWxmLnN0YXRlcy5nZXRfbXV0KCZzZWxlY3RvcikgewogICAgICAgICAgICAgICAgbGV0IHNjcmlwdCA9IFNjcmlwdDo6TGF0aW47CiAgICAgICAgICAgICAgICBmb3IgbGluZV9udW1iZXIgaW4gMC4uc3RhdGUubGluZXMubGVuKCkgewogICAgICAgICAgICAgICAgICAgIGxldCBsaW5lID0gJm11dCBzdGF0ZS5saW5lc1tsaW5lX251bWJlcl07CiAgICAgICAgICAgICAgICAgICAgZm9yIGl0ZW0gaW4gJmxpbmUuZnJhZ21lbnRzIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHZhcnMgPSBzdGF0ZS52YXJzLmdldChpdGVtLnN0eWxlLmZvbnRfdmFycyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzaGFwZXJfa2V5ID0gJml0ZW0uY29udGVudDsKCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByaW50bG4hKCJ7Oj99IC0+IHs6P30iLCBpdGVtLnN0eWxlLmZvbnRfaWQsIHNoYXBlcl9rZXkpOwoKICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGV0IFNvbWUoc2hhcGVyKSA9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLndvcmRfY2FjaGUuZ2V0KCZpdGVtLnN0eWxlLmZvbnRfaWQsIHNoYXBlcl9rZXkpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIGxldCBTb21lKG1ldHJpY3MpID0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5tZXRyaWNzX2NhY2hlLmlubmVyLmdldCgmaXRlbS5zdHlsZS5mb250X2lkKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIGxpbmUucmVuZGVyX2RhdGEucHVzaF9ydW5fd2l0aG91dF9zaGFwZXIoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uc3R5bGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnNjYWxlZF9mb250X3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVfbnVtYmVyIGFzIHUzMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hhcGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYud29yZF9jYWNoZS5mb250X2lkID0gaXRlbS5zdHlsZS5mb250X2lkOwogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLndvcmRfY2FjaGUuY29udGVudCA9IGl0ZW0uY29udGVudC5jbG9uZSgpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgZm9udF9saWJyYXJ5ID0geyAmbXV0IHNlbGYuZm9udHMuaW5uZXIubG9jaygpIH07CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIGxldCBTb21lKGRhdGEpID0gZm9udF9saWJyYXJ5LmdldF9kYXRhKCZpdGVtLnN0eWxlLmZvbnRfaWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtdXQgc2hhcGVyID0gc2VsZgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zY3gKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYnVpbGRlcihkYXRhKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zY3JpcHQoc2NyaXB0KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zaXplKHN0YXRlLnNjYWxlZF9mb250X3NpemUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZlYXR1cmVzKHNlbGYuZm9udF9mZWF0dXJlcy5pdGVyKCkuY29waWVkKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnZhcmlhdGlvbnModmFycy5pdGVyKCkuY29waWVkKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmJ1aWxkKCk7CgogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hhcGVyLmFkZF9zdHIoJnNlbGYud29yZF9jYWNoZS5jb250ZW50KTsKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tZXRyaWNzX2NhY2hlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmlubmVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmVudHJ5KGl0ZW0uc3R5bGUuZm9udF9pZCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAub3JfaW5zZXJ0X3dpdGgofHwgc2hhcGVyLm1ldHJpY3MoKSk7CgogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZS5yZW5kZXJfZGF0YS5wdXNoX3J1bigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLnN0eWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnNjYWxlZF9mb250X3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV9udW1iZXIgYXMgdTMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmbXV0IHNlbGYud29yZF9jYWNoZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gYnVpbGRfbGluZSgmbXV0IHNlbGYsIGxpbmVfbnVtYmVyOiB1c2l6ZSkgewogICAgICAgIGlmIGxldCBTb21lKHNlbGVjdG9yKSA9IHNlbGYuc2VsZWN0b3IgewogICAgICAgICAgICBpZiBsZXQgU29tZShzdGF0ZSkgPSBzZWxmLnN0YXRlcy5nZXRfbXV0KCZzZWxlY3RvcikgewogICAgICAgICAgICAgICAgbGV0IHNjcmlwdCA9IFNjcmlwdDo6TGF0aW47CiAgICAgICAgICAgICAgICBsZXQgbGluZSA9ICZtdXQgc3RhdGUubGluZXNbbGluZV9udW1iZXJdOwogICAgICAgICAgICAgICAgZm9yIGl0ZW0gaW4gJmxpbmUuZnJhZ21lbnRzIHsKICAgICAgICAgICAgICAgICAgICBsZXQgdmFycyA9IHN0YXRlLnZhcnMuZ2V0KGl0ZW0uc3R5bGUuZm9udF92YXJzKTsKICAgICAgICAgICAgICAgICAgICBsZXQgc2hhcGVyX2tleSA9ICZpdGVtLmNvbnRlbnQ7CgogICAgICAgICAgICAgICAgICAgIC8vIHByaW50bG4hKCJ7Oj99IC0+IHs6P30iLCBpdGVtLnN0eWxlLmZvbnRfaWQsIHNoYXBlcl9rZXkpOwoKICAgICAgICAgICAgICAgICAgICBpZiBsZXQgU29tZShzaGFwZXIpID0KICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi53b3JkX2NhY2hlLmdldCgmaXRlbS5zdHlsZS5mb250X2lkLCBzaGFwZXJfa2V5KQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGV0IFNvbWUobWV0cmljcykgPQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUubWV0cmljc19jYWNoZS5pbm5lci5nZXQoJml0ZW0uc3R5bGUuZm9udF9pZCkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGluZS5yZW5kZXJfZGF0YS5wdXNoX3J1bl93aXRob3V0X3NoYXBlcigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLnN0eWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnNjYWxlZF9mb250X3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV9udW1iZXIgYXMgdTMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgICAgIHNlbGYud29yZF9jYWNoZS5mb250X2lkID0gaXRlbS5zdHlsZS5mb250X2lkOwogICAgICAgICAgICAgICAgICAgIHNlbGYud29yZF9jYWNoZS5jb250ZW50ID0gaXRlbS5jb250ZW50LmNsb25lKCk7CiAgICAgICAgICAgICAgICAgICAgbGV0IGZvbnRfbGlicmFyeSA9IHsgJm11dCBzZWxmLmZvbnRzLmlubmVyLmxvY2soKSB9OwogICAgICAgICAgICAgICAgICAgIGlmIGxldCBTb21lKGRhdGEpID0gZm9udF9saWJyYXJ5LmdldF9kYXRhKCZpdGVtLnN0eWxlLmZvbnRfaWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG11dCBzaGFwZXIgPSBzZWxmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuc2N4CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYnVpbGRlcihkYXRhKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNjcmlwdChzY3JpcHQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuc2l6ZShzdGF0ZS5zY2FsZWRfZm9udF9zaXplKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZlYXR1cmVzKHNlbGYuZm9udF9mZWF0dXJlcy5pdGVyKCkuY29waWVkKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudmFyaWF0aW9ucyh2YXJzLml0ZXIoKS5jb3BpZWQoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5idWlsZCgpOwoKICAgICAgICAgICAgICAgICAgICAgICAgc2hhcGVyLmFkZF9zdHIoJnNlbGYud29yZF9jYWNoZS5jb250ZW50KTsKCiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAubWV0cmljc19jYWNoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLmlubmVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZW50cnkoaXRlbS5zdHlsZS5mb250X2lkKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLm9yX2luc2VydF93aXRoKHx8IHNoYXBlci5tZXRyaWNzKCkpOwoKICAgICAgICAgICAgICAgICAgICAgICAgbGluZS5yZW5kZXJfZGF0YS5wdXNoX3J1bigKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uc3R5bGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5zY2FsZWRfZm9udF9zaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV9udW1iZXIgYXMgdTMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hhcGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgJm11dCBzZWxmLndvcmRfY2FjaGUsCiAgICAgICAgICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9CgpwdWIgc3RydWN0IFdvcmRDYWNoZSB7CiAgICBwdWIgaW5uZXI6IEZ4SGFzaE1hcDx1c2l6ZSwgTHJ1Q2FjaGU8U3RyaW5nLCBWZWM8T3duZWRHbHlwaENsdXN0ZXI+Pj4sCiAgICBzdGFzaDogVmVjPE93bmVkR2x5cGhDbHVzdGVyPiwKICAgIGZvbnRfaWQ6IHVzaXplLAogICAgY29udGVudDogU3RyaW5nLAp9CgppbXBsIFdvcmRDYWNoZSB7CiAgICBwdWIgZm4gbmV3KCkgLT4gU2VsZiB7CiAgICAgICAgV29yZENhY2hlIHsKICAgICAgICAgICAgaW5uZXI6IEZ4SGFzaE1hcDo6ZGVmYXVsdCgpLAogICAgICAgICAgICBzdGFzaDogdmVjIVtdLAogICAgICAgICAgICBmb250X2lkOiAwLAogICAgICAgICAgICBjb250ZW50OiBTdHJpbmc6Om5ldygpLAogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBnZXQoCiAgICAgICAgJm11dCBzZWxmLAogICAgICAgIGZvbnRfaWQ6ICZ1c2l6ZSwKICAgICAgICBjb250ZW50OiAmU3RyaW5nLAogICAgKSAtPiBPcHRpb248JlZlYzxPd25lZEdseXBoQ2x1c3Rlcj4+IHsKICAgICAgICBpZiBsZXQgU29tZShjYWNoZSkgPSBzZWxmLmlubmVyLmdldF9tdXQoZm9udF9pZCkgewogICAgICAgICAgICByZXR1cm4gY2FjaGUuZ2V0KGNvbnRlbnQpOwogICAgICAgIH0KICAgICAgICBOb25lCiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gYWRkX2dseXBoX2NsdXN0ZXIoJm11dCBzZWxmLCBnbHlwaF9jbHVzdGVyOiAmR2x5cGhDbHVzdGVyKSB7CiAgICAgICAgc2VsZi5zdGFzaC5wdXNoKGdseXBoX2NsdXN0ZXIuaW50bygpKTsKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBmaW5pc2goJm11dCBzZWxmKSB7CiAgICAgICAgaWYgIXNlbGYuY29udGVudC5pc19lbXB0eSgpICYmICFzZWxmLnN0YXNoLmlzX2VtcHR5KCkgewogICAgICAgICAgICBpZiBsZXQgU29tZShjYWNoZSkgPSBzZWxmLmlubmVyLmdldF9tdXQoJnNlbGYuZm9udF9pZCkgewogICAgICAgICAgICAgICAgLy8gcHJpbnRsbiEoIns6P30gezo/fSIsIHNlbGYuY29udGVudCwgY2FjaGUubGVuKCkpOwogICAgICAgICAgICAgICAgY2FjaGUucHV0KAogICAgICAgICAgICAgICAgICAgIHN0ZDo6bWVtOjp0YWtlKCZtdXQgc2VsZi5jb250ZW50KSwKICAgICAgICAgICAgICAgICAgICBzdGQ6Om1lbTo6dGFrZSgmbXV0IHNlbGYuc3Rhc2gpLAogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIC8vIElmIGZvbnQgaWQgaXMgbWFpbgogICAgICAgICAgICAgICAgbGV0IHNpemUgPSBpZiBzZWxmLmZvbnRfaWQgPT0gMCB7IDUxMiB9IGVsc2UgeyAxMjggfTsKICAgICAgICAgICAgICAgIGxldCBtdXQgY2FjaGUgPSBMcnVDYWNoZTo6bmV3KE5vblplcm9Vc2l6ZTo6bmV3KHNpemUpLnVud3JhcCgpKTsKICAgICAgICAgICAgICAgIGNhY2hlLnB1dCgKICAgICAgICAgICAgICAgICAgICBzdGQ6Om1lbTo6dGFrZSgmbXV0IHNlbGYuY29udGVudCksCiAgICAgICAgICAgICAgICAgICAgc3RkOjptZW06OnRha2UoJm11dCBzZWxmLnN0YXNoKSwKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBzZWxmLmlubmVyLmluc2VydChzZWxmLmZvbnRfaWQsIGNhY2hlKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgc2VsZi5mb250X2lkID0gMDsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBzZWxmLnN0YXNoLmNsZWFyKCk7CiAgICAgICAgc2VsZi5mb250X2lkID0gMDsKICAgICAgICBzZWxmLmNvbnRlbnQuY2xlYXIoKTsKICAgIH0KfQoKI1tkZXJpdmUoRGVmYXVsdCldCnN0cnVjdCBNZXRyaWNzQ2FjaGUgewogICAgcHViIGlubmVyOiBGeEhhc2hNYXA8dXNpemUsIE1ldHJpY3M+LAp9CgAAAAAAAAAABUwAAAAAAAAAAAAAAAAAAAAAAAAFTAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAIAAAARAwAAAAAAABwDAAAAAAAAAAAAAAAA8L/7FgAAAAAAAAYXAAAAAAAAAAAAAAAA8L8" + ] + ] + }, + { + "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/lib.rs", + "redo_stack": + [ + [ + 8, + 1, + "insert", + { + "characters": "content" + }, + "EAAAAFwAAAAAAAAAXAAAAAAAAAABAAAAdF4CAAAAAAAAXgIAAAAAAAABAAAAdFsAAAAAAAAAWwAAAAAAAAABAAAAblwCAAAAAAAAXAIAAAAAAAABAAAAbloAAAAAAAAAWgAAAAAAAAABAAAAZVoCAAAAAAAAWgIAAAAAAAABAAAAZVkAAAAAAAAAWQAAAAAAAAABAAAAdFgCAAAAAAAAWAIAAAAAAAABAAAAdFgAAAAAAAAAWAAAAAAAAAABAAAAblYCAAAAAAAAVgIAAAAAAAABAAAAblcAAAAAAAAAVwAAAAAAAAABAAAAb1QCAAAAAAAAVAIAAAAAAAABAAAAb1cAAAAAAAAAXQAAAAAAAAAAAAAAVgAAAAAAAABWAAAAAAAAAAEAAABjWQIAAAAAAABfAgAAAAAAAAAAAABYAgAAAAAAAFgCAAAAAAAAAQAAAGM", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAIAAABdAAAAAAAAAF0AAAAAAAAAAAAAAAAA8L9gAgAAAAAAAGACAAAAAAAAAAAAAAAA8L8" + ] + ], + "settings": + { + "buffer_size": 718, + "encoding": "UTF-8", + "line_ending": "Unix" + } + }, + { + "file": "/Users/rapha/Documents/a/rio/sugarloaf/Cargo.toml", + "settings": + { + "buffer_size": 6744, + "line_ending": "Unix" + }, + "undo_stack": + [ + [ + 10, + 1, + "paste", + null, + "AgAAAKcDAAAAAAAAuwMAAAAAAAAAAAAAuwMAAAAAAAC7AwAAAAAAAC8AAAB7IHZlcnNpb24gPSAiMS4xNy4wIiwgZmVhdHVyZXMgPSBbICJkZXJpdmUiIF0gfQ", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACnAwAAAAAAANYDAAAAAAAA////////738" + ], + [ + 13, + 1, + "paste", + null, + "AgAAAMYDAAAAAAAA2gMAAAAAAAAAAAAA2gMAAAAAAADaAwAAAAAAAAgAAAAiMC4xLjQwIg", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADOAwAAAAAAAMYDAAAAAAAAAAAAAAAA8L8" + ], + [ + 25, + 1, + "paste", + null, + "AgAAAO0EAAAAAAAAAQUAAAAAAAAAAAAAAQUAAAAAAAABBQAAAAAAAAcAAAAiMC4yLjAi", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADtBAAAAAAAAPQEAAAAAAAA////////738" + ], + [ + 35, + 1, + "insert", + { + "characters": "26" + }, + "AwAAAEgGAAAAAAAASQYAAAAAAAAAAAAASQYAAAAAAABJBgAAAAAAAAIAAAAyNUkGAAAAAAAASgYAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABIBgAAAAAAAEoGAAAAAAAAAAAAAAAA8L8" + ], + [ + 37, + 1, + "left_delete", + null, + "AQAAAEsGAAAAAAAASwYAAAAAAAABAAAAMA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABMBgAAAAAAAEwGAAAAAAAAAAAAAAAA8L8" + ], + [ + 38, + 1, + "insert", + { + "characters": "2" + }, + "AQAAAEsGAAAAAAAATAYAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABLBgAAAAAAAEsGAAAAAAAAAAAAAAAA8L8" + ], + [ + 43, + 1, + "revert", + null, + "AwAAAAAAAAAAAAAAAAAAAAAAAABYGgAAW3BhY2thZ2VdCm5hbWUgPSAic3VnYXJsb2FmIgp2ZXJzaW9uLndvcmtzcGFjZSA9IHRydWUKZWRpdGlvbi53b3Jrc3BhY2UgPSB0cnVlCmxpY2Vuc2Uud29ya3NwYWNlID0gdHJ1ZQphdXRob3JzID0gWyJSYXBoYWVsIEFtb3JpbSA8cmFwaGE4NTBAZ21haWwuY29tPiJdCmluY2x1ZGUgPSBbCiAgIkNhcmdvLnRvbWwiLAogICJzcmMvKiovKi50dGYiLAogICJzcmMvKiovKi5vdGYiLAogICJzcmMvKiovKi53Z3NsIiwKICAic3JjLyoqLyoucnMiCl0KZGVzY3JpcHRpb24gPSAiU3VnYXJsb2FmIGlzIFJpbyByZW5kZXJpbmcgZW5naW5lLCBkZXNpZ25lZCB0byBiZSBtdWx0aXBsYXRmb3JtLiBJdCBpcyBiYXNlZCBvbiBXZWJHUFUsIFJ1c3QgbGlicmFyeSBmb3IgRGVza3RvcHMgYW5kIFdlYkFzc2VtYmx5IGZvciBXZWIgKEphdmFTY3JpcHQpLiBUaGlzIHByb2plY3QgaXMgY3JlYXRlZCBhbmQgbWFpbnRhaW5lZCBmb3IgUmlvIHRlcm1pbmFsIHB1cnBvc2VzIGJ1dCBmZWVsIGZyZWUgdG8gdXNlIGl0LiIKZG9jdW1lbnRhdGlvbiA9ICJodHRwczovL2RvY3MucnMvY3JhdGUvc3VnYXJsb2FmL2xhdGVzdCIKcmVwb3NpdG9yeSA9ICJodHRwczovL2dpdGh1Yi5jb20vcmFwaGFtb3JpbS9zdWdhcmxvYWYiCgpbbGliXQpjcmF0ZS10eXBlID0gWyJjZHlsaWIiLCAicmxpYiJdCgpbcGFja2FnZS5tZXRhZGF0YS5kb2NzLnJzXQphbGwtZmVhdHVyZXMgPSB0cnVlCnJ1c3Rkb2MtYXJncyA9IFsiLS1jZmciLCAiZG9jc3JzIl0KdGFyZ2V0cyA9IFsKICAgICJ4ODZfNjQtdW5rbm93bi1saW51eC1nbnUiLAogICAgIng4Nl82NC1hcHBsZS1kYXJ3aW4iLAogICAgIng4Nl82NC1wYy13aW5kb3dzLW1zdmMiLAogICAgIndhc20zMi11bmtub3duLXVua25vd24iLApdCgpbZGVwZW5kZW5jaWVzXQp3Z3B1ID0geyB3b3Jrc3BhY2UgPSB0cnVlIH0KYnl0ZW11Y2sgPSB7IHdvcmtzcGFjZSA9IHRydWUgfQp0cmFjaW5nID0geyB3b3Jrc3BhY2UgPSB0cnVlIH0Kc2VyZGUgPSB7IHZlcnNpb24gPSAiMS4wLjIwOCIsIGZlYXR1cmVzID0gWyJkZXJpdmUiXSB9CnR3b3gtaGFzaCA9IHsgdmVyc2lvbiA9ICIxLjYuMyIsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CmltYWdlX3JzID0geyBwYWNrYWdlID0gImltYWdlIiwgdmVyc2lvbiA9ICIwLjI1LjUiLCBkZWZhdWx0LWZlYXR1cmVzID0gZmFsc2UsIGZlYXR1cmVzID0gWyJnaWYiLCAianBlZyIsICJpY28iLCAicG5nIiwgInBubSIsICJ3ZWJwIiwgImJtcCJdIH0KdW5pY29kZS13aWR0aCA9IHsgd29ya3NwYWNlID0gdHJ1ZSB9Cmd1aWxsb3RpZXJlID0gIjAuNi4yIgpvcmRlcmVkLWZsb2F0ID0gIjQuNS4wIgpydXN0Yy1oYXNoID0gIjIuMC4wIgpyYXctd2luZG93LWhhbmRsZSA9IHsgdmVyc2lvbiA9ICIwLjYuMiIsIGZlYXR1cmVzID0gWyJzdGQiXSB9CnBhcmtpbmdfbG90ID0geyB2ZXJzaW9uID0gIjAuMTIuMyIsIGZlYXR1cmVzID0gWyJuaWdodGx5IiwgImhhcmR3YXJlLWxvY2stZWxpc2lvbiJdIH0KYWJfZ2x5cGggPSAiMC4yLjI5IgpsaW5rZWQtaGFzaC1tYXAgPSAiMC41LjYiCnhpLXVuaWNvZGUgPSAiMC4zLjAiCmFwcHJveCA9ICIwLjUuMSIKbHJ1ID0gIjAuMTIuNSIKc2tyaWZhID0gIjAuMjYuMiIKaGFsZmJyb3duID0gIjAuMi41IgpudW0tdHJhaXRzID0gIjAuMi4xOSIKeWF6aSA9IHsgdmVyc2lvbiA9ICIwLjIuMCIsIG9wdGlvbmFsID0gdHJ1ZSB9Cnplbm8gPSB7IHZlcnNpb24gPSAiMC4yLjMiLCBvcHRpb25hbCA9IHRydWUsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CmZ1dHVyZXMgPSAiMC4zLjMxIgoKbGlicmFzaGFkZXItY29tbW9uID0gIjAuNi4yIgpsaWJyYXNoYWRlci1wcmVzZXRzID0gIjAuNi4yIgpsaWJyYXNoYWRlci1wcmVwcm9jZXNzID0gIjAuNi4yIgpsaWJyYXNoYWRlci1wYWNrID0gIjAuNi4yIgpsaWJyYXNoYWRlci1yZWZsZWN0ID0geyB2ZXJzaW9uID0gIjAuNi4yIiwgZmVhdHVyZXMgPSBbInN0YWJsZSIsICJ3Z3NsIl0sIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CmxpYnJhc2hhZGVyLXJ1bnRpbWUgPSAiMC42LjIiCmxpYnJhc2hhZGVyLWNhY2hlID0gIjAuNi4yIgp0aGlzZXJyb3IgPSAiMi4wLjEiCmFycmF5LWNvbmNhdCA9ICIwLjUuMiIKClt0YXJnZXQuJ2NmZyhub3QodGFyZ2V0X2FyY2ggPSAid2FzbTMyIikpJy5kZXBlbmRlbmNpZXNdCmNyb3NzYmVhbS1jaGFubmVsID0gIjAuNS4xMyIKY3Jvc3NiZWFtLWRlcXVlID0gIjAuOC41IgpyYXlvbiA9ICIxLjEwLjAiCnR3b3gtaGFzaCA9IHsgdmVyc2lvbiA9ICIxLjYuMyIsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSwgZmVhdHVyZXMgPSBbInN0ZCJdIH0KbWVtbWFwMiA9ICIwLjkuMyIKc2xvdG1hcCA9IHsgdmVyc2lvbiA9ICIxLjAuNyIsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CnRpbnl2ZWMgPSB7IHZlcnNpb24gPSAiMS42LjAiLCBmZWF0dXJlcyA9IFsiYWxsb2MiXSB9CnR0Zi1wYXJzZXIgPSB7IHZlcnNpb24gPSAiMC4yNS4wIiB9CgpbdGFyZ2V0LidjZmcoYWxsKHVuaXgsIG5vdChhbnkodGFyZ2V0X29zID0gIm1hY29zIiwgdGFyZ2V0X29zID0gImFuZHJvaWQiKSkpKScuZGVwZW5kZW5jaWVzXQpmb250Y29uZmlnLXBhcnNlciA9IHsgdmVyc2lvbiA9ICIwLjUuNyIsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CgpbZGV2LWRlcGVuZGVuY2llc10KcmlvLXdpbmRvdyA9ICIwLjIuMSIKcG5nID0gIjAuMTcuOCIKZGVmbGF0ZSA9ICIxLjAuMCIKY3JpdGVyaW9uID0gIjAuNS4xIgoKW2ZlYXR1cmVzXQpkZWZhdWx0ID0gWyJzY2FsZSIsICJyZW5kZXIiXQpzY2FsZSA9IFsieWF6aSIsICJ6ZW5vIl0KcmVuZGVyID0gWyJzY2FsZSIsICJ6ZW5vL2V2YWwiXQoKW3RhcmdldC4nY2ZnKHRhcmdldF9hcmNoID0gIndhc20zMiIpJy5kZXBlbmRlbmNpZXNdCmNvbnNvbGVfZXJyb3JfcGFuaWNfaG9vayA9ICIwLjEuNyIKY29uc29sZV9sb2cgPSAiMC4yLjIiCmpzLXN5cyA9ICIwLjMuNjEiCndhc20tYmluZGdlbiA9ICIwLjIuODciCndhc20tYmluZGdlbi1mdXR1cmVzID0gIjAuNC4zNCIKd2FzbS1iaW5kZ2VuLXRlc3QgPSAiMC4zLjQyIgp3ZWItc3lzID0geyB2ZXJzaW9uID0gIjAuMy42MSIsIGZlYXR1cmVzID0gWwogICAgIkxvY2F0aW9uIiwKICAgICJEb2N1bWVudCIsCiAgICAiTmF2aWdhdG9yIiwKICAgICJOb2RlIiwKICAgICJOb2RlTGlzdCIsCiAgICAiR3B1IiwKICAgICJHcHVBZGFwdGVyIiwKICAgICJHcHVBZGRyZXNzTW9kZSIsCiAgICAiR3B1QXV0b0xheW91dE1vZGUiLAogICAgIkdwdUJpbmRHcm91cCIsCiAgICAiR3B1QmluZEdyb3VwRGVzY3JpcHRvciIsCiAgICAiR3B1QmluZEdyb3VwRW50cnkiLAogICAgIkdwdUJpbmRHcm91cExheW91dCIsCiAgICAiR3B1QmluZEdyb3VwTGF5b3V0RGVzY3JpcHRvciIsCiAgICAiR3B1QmluZEdyb3VwTGF5b3V0RW50cnkiLAogICAgIkdwdUJsZW5kQ29tcG9uZW50IiwKICAgICJHcHVCbGVuZEZhY3RvciIsCiAgICAiR3B1QmxlbmRPcGVyYXRpb24iLAogICAgIkdwdUJsZW5kU3RhdGUiLAogICAgIkdwdUJ1ZmZlciIsCiAgICAiR3B1QnVmZmVyQmluZGluZyIsCiAgICAiR3B1QnVmZmVyQmluZGluZ0xheW91dCIsCiAgICAiR3B1QnVmZmVyQmluZGluZ1R5cGUiLAogICAgIkdwdUJ1ZmZlckRlc2NyaXB0b3IiLAogICAgIkdwdUNhbnZhc0FscGhhTW9kZSIsCiAgICAiR3B1Q2FudmFzQ29udGV4dCIsCiAgICAiR3B1Q2FudmFzQ29uZmlndXJhdGlvbiIsCiAgICAiR3B1Q29sb3JEaWN0IiwKICAgICJHcHVDb2xvclRhcmdldFN0YXRlIiwKICAgICJHcHVDb21tYW5kQnVmZmVyIiwKICAgICJHcHVDb21tYW5kQnVmZmVyRGVzY3JpcHRvciIsCiAgICAiR3B1Q29tbWFuZEVuY29kZXIiLAogICAgIkdwdUNvbW1hbmRFbmNvZGVyRGVzY3JpcHRvciIsCiAgICAiR3B1Q29tcGFyZUZ1bmN0aW9uIiwKICAgICJHcHVDb21waWxhdGlvbkluZm8iLAogICAgIkdwdUNvbXBpbGF0aW9uTWVzc2FnZSIsCiAgICAiR3B1Q29tcGlsYXRpb25NZXNzYWdlVHlwZSIsCiAgICAiR3B1Q29tcHV0ZVBhc3NEZXNjcmlwdG9yIiwKICAgICJHcHVDb21wdXRlUGFzc0VuY29kZXIiLAogICAgIkdwdUNvbXB1dGVQaXBlbGluZSIsCiAgICAiR3B1Q29tcHV0ZVBpcGVsaW5lRGVzY3JpcHRvciIsCiAgICAiR3B1Q3VsbE1vZGUiLAogICAgIkdwdURlcHRoU3RlbmNpbFN0YXRlIiwKICAgICJHcHVEZXZpY2UiLAogICAgIkdwdURldmljZURlc2NyaXB0b3IiLAogICAgIkdwdURldmljZUxvc3RJbmZvIiwKICAgICJHcHVEZXZpY2VMb3N0UmVhc29uIiwKICAgICJHcHVFcnJvciIsCiAgICAiR3B1RXJyb3JGaWx0ZXIiLAogICAgIyAiR3B1RXh0ZW50MmREaWN0IiwgTm90IHlldCBpbXBsZW1lbnRlZCBpbiB3ZWJfc3lzCiAgICAiR3B1RXh0ZW50M2REaWN0IiwKICAgICJHcHVGZWF0dXJlTmFtZSIsCiAgICAiR3B1RmlsdGVyTW9kZSIsCiAgICAiR3B1RnJhZ21lbnRTdGF0ZSIsCiAgICAiR3B1RnJvbnRGYWNlIiwKICAgICJHcHVJbWFnZUNvcHlCdWZmZXIiLAogICAgIkdwdUltYWdlQ29weUV4dGVybmFsSW1hZ2UiLAogICAgIkdwdUltYWdlQ29weVRleHR1cmUiLAogICAgIkdwdUltYWdlQ29weVRleHR1cmVUYWdnZWQiLAogICAgIkdwdUltYWdlRGF0YUxheW91dCIsCiAgICAiR3B1SW5kZXhGb3JtYXQiLAogICAgIkdwdUxvYWRPcCIsCiAgICAiZ3B1X21hcF9tb2RlIiwKICAgICJHcHVNaXBtYXBGaWx0ZXJNb2RlIiwKICAgICJHcHVNdWx0aXNhbXBsZVN0YXRlIiwKICAgICJHcHVPYmplY3REZXNjcmlwdG9yQmFzZSIsCiAgICAiR3B1T3JpZ2luMmREaWN0IiwKICAgICJHcHVPcmlnaW4zZERpY3QiLAogICAgIkdwdU91dE9mTWVtb3J5RXJyb3IiLAogICAgIkdwdVBpcGVsaW5lRGVzY3JpcHRvckJhc2UiLAogICAgIkdwdVBpcGVsaW5lTGF5b3V0IiwKICAgICJHcHVQaXBlbGluZUxheW91dERlc2NyaXB0b3IiLAogICAgIkdwdVBvd2VyUHJlZmVyZW5jZSIsCiAgICAiR3B1UHJpbWl0aXZlU3RhdGUiLAogICAgIkdwdVByaW1pdGl2ZVRvcG9sb2d5IiwKICAgICJHcHVQcm9ncmFtbWFibGVTdGFnZSIsCiAgICAiR3B1UXVlcnlTZXQiLAogICAgIkdwdVF1ZXJ5U2V0RGVzY3JpcHRvciIsCiAgICAiR3B1UXVlcnlUeXBlIiwKICAgICJHcHVRdWV1ZSIsCiAgICAiR3B1UmVuZGVyQnVuZGxlIiwKICAgICJHcHVSZW5kZXJCdW5kbGVEZXNjcmlwdG9yIiwKICAgICJHcHVSZW5kZXJCdW5kbGVFbmNvZGVyIiwKICAgICJHcHVSZW5kZXJCdW5kbGVFbmNvZGVyRGVzY3JpcHRvciIsCiAgICAiR3B1UmVuZGVyUGFzc0NvbG9yQXR0YWNobWVudCIsCiAgICAiR3B1UmVuZGVyUGFzc0RlcHRoU3RlbmNpbEF0dGFjaG1lbnQiLAogICAgIkdwdVJlbmRlclBhc3NEZXNjcmlwdG9yIiwKICAgICJHcHVSZW5kZXJQYXNzRW5jb2RlciIsCiAgICAiR3B1UmVuZGVyUGlwZWxpbmUiLAogICAgIkdwdVJlbmRlclBpcGVsaW5lRGVzY3JpcHRvciIsCiAgICAiR3B1UmVxdWVzdEFkYXB0ZXJPcHRpb25zIiwKICAgICJHcHVTYW1wbGVyIiwKICAgICJHcHVTYW1wbGVyQmluZGluZ0xheW91dCIsCiAgICAiR3B1U2FtcGxlckJpbmRpbmdUeXBlIiwKICAgICJHcHVTYW1wbGVyRGVzY3JpcHRvciIsCiAgICAiR3B1U2hhZGVyTW9kdWxlIiwKICAgICJHcHVTaGFkZXJNb2R1bGVEZXNjcmlwdG9yIiwKICAgICJHcHVTdGVuY2lsRmFjZVN0YXRlIiwKICAgICJHcHVTdGVuY2lsT3BlcmF0aW9uIiwKICAgICJHcHVTdG9yYWdlVGV4dHVyZUFjY2VzcyIsCiAgICAiR3B1U3RvcmFnZVRleHR1cmVCaW5kaW5nTGF5b3V0IiwKICAgICJHcHVTdG9yZU9wIiwKICAgICJHcHVTdXBwb3J0ZWRGZWF0dXJlcyIsCiAgICAiR3B1U3VwcG9ydGVkTGltaXRzIiwKICAgICJHcHVUZXh0dXJlIiwKICAgICJHcHVUZXh0dXJlQXNwZWN0IiwKICAgICJHcHVUZXh0dXJlQmluZGluZ0xheW91dCIsCiAgICAiR3B1VGV4dHVyZURlc2NyaXB0b3IiLAogICAgIkdwdVRleHR1cmVEaW1lbnNpb24iLAogICAgIkdwdVRleHR1cmVGb3JtYXQiLAogICAgIkdwdVRleHR1cmVTYW1wbGVUeXBlIiwKICAgICJHcHVUZXh0dXJlVmlldyIsCiAgICAiR3B1VGV4dHVyZVZpZXdEZXNjcmlwdG9yIiwKICAgICJHcHVUZXh0dXJlVmlld0RpbWVuc2lvbiIsCiAgICAiR3B1VW5jYXB0dXJlZEVycm9yRXZlbnQiLAogICAgIkdwdVVuY2FwdHVyZWRFcnJvckV2ZW50SW5pdCIsCiAgICAiR3B1VmFsaWRhdGlvbkVycm9yIiwKICAgICJHcHVWZXJ0ZXhBdHRyaWJ1dGUiLAogICAgIkdwdVZlcnRleEJ1ZmZlckxheW91dCIsCiAgICAiR3B1VmVydGV4Rm9ybWF0IiwKICAgICJHcHVWZXJ0ZXhTdGF0ZSIsCiAgICAiR3B1VmVydGV4U3RlcE1vZGUiLAogICAgIkh0bWxDYW52YXNFbGVtZW50IiwKICAgICJPZmZzY3JlZW5DYW52YXMiLAogICAgIkltYWdlQml0bWFwIiwKICAgICJJbWFnZUJpdG1hcFJlbmRlcmluZ0NvbnRleHQiLAogICAgIldpbmRvdyIsCiAgICAiV29ya2VyR2xvYmFsU2NvcGUiLAogICAgIldvcmtlck5hdmlnYXRvciIKXSB9CgpbdGFyZ2V0LidjZmcodGFyZ2V0X2FyY2ggPSAid2FzbTMyIiknLmRldi1kZXBlbmRlbmNpZXNdCndlYi1zeXMgPSB7IHZlcnNpb24gPSAiMC4zLjYxIiwgZmVhdHVyZXMgPSBbCiAgICAiTG9jYXRpb24iLAogICAgIkJsb2IiLAogICAgIlJlcXVlc3RJbml0IiwKICAgICJSZXF1ZXN0TW9kZSIsCiAgICAiUmVxdWVzdCIsCiAgICAiUmVzcG9uc2UiLAogICAgIldlYkdsMlJlbmRlcmluZ0NvbnRleHQiLAogICAgIkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyZCIKXX0KAAAAAAAAAABYGgAAAAAAAAAAAAAAAAAAAAAAAFgaAAAAAAAAAAAAAA", + "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAACBQAAAAAAAA0FAAAAAAAAAAAAAAAA8L8" + ] + ] + }, + { + "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/bindings/mod.rs", + "settings": + { + "buffer_size": 64085, + "line_ending": "Unix" + }, + "undo_stack": + [ + [ + 200, + 1, + "revert", + null, + "AgAAAAAAAAAAAAAAAAAAAAAAAABV+gAALy8gQmluZGluZzxUPiwgTW91c2VBY3Rpb24sIEJpbmRpbmdNb2RlLCBBY3Rpb24sIGRlZmF1bHRfa2V5X2JpbmRpbmdzIGFuZCBpbmNsdWRpbmcgdGhlaXIgY29tbWVudHMKLy8gd2FzIG9yaWdpbmFsbHkgdGFrZW4gZnJvbSBodHRwczovL2dpdGh1Yi5jb20vYWxhY3JpdHR5L2FsYWNyaXR0eS9ibG9iL2UzNWU1YWQxNGZjZTg0NTZhZmRkODlmMmIzOTJiOTkyNGJiMjc0NzEvYWxhY3JpdHR5L3NyYy9jb25maWcvYmluZGluZ3MucnMKLy8gd2hpY2ggaXMgbGljZW5zZWQgdW5kZXIgQXBhY2hlIDIuMCBsaWNlbnNlLgoKcHViIG1vZCBraXR0eV9rZXlib2FyZDsKCnVzZSBjcmF0ZTo6Y3Jvc3N3b3Jkczo6dmlfbW9kZTo6VmlNb3Rpb247CnVzZSBjcmF0ZTo6Y3Jvc3N3b3Jkczo6TW9kZTsKdXNlIGJpdGZsYWdzOjpiaXRmbGFnczsKdXNlIHJpb19iYWNrZW5kOjpjb25maWc6OmJpbmRpbmdzOjpLZXlCaW5kaW5nIGFzIENvbmZpZ0tleUJpbmRpbmc7CnVzZSByaW9fYmFja2VuZDo6Y29uZmlnOjprZXlib2FyZDo6S2V5Ym9hcmQgYXMgQ29uZmlnS2V5Ym9hcmQ7CnVzZSByaW9fd2luZG93OjpldmVudDo6TW91c2VCdXR0b247CnVzZSByaW9fd2luZG93OjprZXlib2FyZDo6S2V5OjoqOwp1c2UgcmlvX3dpbmRvdzo6a2V5Ym9hcmQ6Ok5hbWVkS2V5OjoqOwp1c2UgcmlvX3dpbmRvdzo6a2V5Ym9hcmQ6OntLZXksIEtleUxvY2F0aW9uLCBNb2RpZmllcnNTdGF0ZSwgUGh5c2ljYWxLZXl9Owp1c2Ugc3RkOjpmbXQ6OkRlYnVnOwovLyB1c2UgcmlvX3dpbmRvdzo6cGxhdGZvcm06OnNjYW5jb2RlOjpQaHlzaWNhbEtleUV4dFNjYW5jb2RlOwoKI1tkZXJpdmUoRGVidWcsIENsb25lLCBQYXJ0aWFsRXEsIEVxKV0KcHViIGVudW0gRm9udFNpemVBY3Rpb24gewogICAgSW5jcmVhc2UsCiAgICBEZWNyZWFzZSwKICAgIFJlc2V0LAp9CgovLy8gTW91c2UgYmluZGluZyBzcGVjaWZpYyBhY3Rpb25zLgojW2Rlcml2ZShEZWJ1ZywgQ29weSwgQ2xvbmUsIFBhcnRpYWxFcSwgRXEpXQpwdWIgZW51bSBNb3VzZUFjdGlvbiB7CiAgICAvLy8gRXhwYW5kIHRoZSBzZWxlY3Rpb24gdG8gdGhlIGN1cnJlbnQgbW91c2UgY3Vyc29yIHBvc2l0aW9uLgogICAgRXhwYW5kU2VsZWN0aW9uLAp9CgppbXBsIEZyb208TW91c2VBY3Rpb24+IGZvciBBY3Rpb24gewogICAgZm4gZnJvbShhY3Rpb246IE1vdXNlQWN0aW9uKSAtPiBTZWxmIHsKICAgICAgICBTZWxmOjpNb3VzZShhY3Rpb24pCiAgICB9Cn0KCi8vLyBTZWFyY2ggbW9kZSBzcGVjaWZpYyBhY3Rpb25zLgojW2FsbG93KGNsaXBweTo6ZW51bV92YXJpYW50X25hbWVzKV0KI1tkZXJpdmUoRGVidWcsIENvcHksIENsb25lLCBQYXJ0aWFsRXEsIEVxKV0KcHViIGVudW0gU2VhcmNoQWN0aW9uIHsKICAgIC8vLyBNb3ZlIHRoZSBmb2N1cyB0byB0aGUgbmV4dCBzZWFyY2ggbWF0Y2guCiAgICBTZWFyY2hGb2N1c05leHQsCiAgICAvLy8gTW92ZSB0aGUgZm9jdXMgdG8gdGhlIHByZXZpb3VzIHNlYXJjaCBtYXRjaC4KICAgIFNlYXJjaEZvY3VzUHJldmlvdXMsCiAgICAvLy8gQ29uZmlybSB0aGUgYWN0aXZlIHNlYXJjaC4KICAgIFNlYXJjaENvbmZpcm0sCiAgICAvLy8gQ2FuY2VsIHRoZSBhY3RpdmUgc2VhcmNoLgogICAgU2VhcmNoQ2FuY2VsLAogICAgLy8vIFJlc2V0IHRoZSBzZWFyY2ggcmVnZXguCiAgICBTZWFyY2hDbGVhciwKICAgIC8vLyBEZWxldGUgdGhlIGxhc3Qgd29yZCBpbiB0aGUgc2VhcmNoIHJlZ2V4LgogICAgU2VhcmNoRGVsZXRlV29yZCwKICAgIC8vLyBHbyB0byB0aGUgcHJldmlvdXMgcmVnZXggaW4gdGhlIHNlYXJjaCBoaXN0b3J5LgogICAgU2VhcmNoSGlzdG9yeVByZXZpb3VzLAogICAgLy8vIEdvIHRvIHRoZSBuZXh0IHJlZ2V4IGluIHRoZSBzZWFyY2ggaGlzdG9yeS4KICAgIFNlYXJjaEhpc3RvcnlOZXh0LAp9CgppbXBsIEZyb208U2VhcmNoQWN0aW9uPiBmb3IgQWN0aW9uIHsKICAgIGZuIGZyb20oYWN0aW9uOiBTZWFyY2hBY3Rpb24pIC0+IFNlbGYgewogICAgICAgIFNlbGY6OlNlYXJjaChhY3Rpb24pCiAgICB9Cn0KCiNbZGVyaXZlKERlYnVnLCBDbG9uZSwgUGFydGlhbEVxLCBFcSldCnB1YiBzdHJ1Y3QgQmluZGluZzxUPiB7CiAgICAvLy8gTW9kaWZpZXIga2V5cyByZXF1aXJlZCB0byBhY3RpdmF0ZSBiaW5kaW5nLgogICAgcHViIG1vZHM6IE1vZGlmaWVyc1N0YXRlLAoKICAgIC8vLyBTdHJpbmcgdG8gc2VuZCB0byBQVFkgaWYgbW9kcyBhbmQgbW9kZSBtYXRjaC4KICAgIHB1YiBhY3Rpb246IEFjdGlvbiwKCiAgICAvLy8gQmluZGluZyBtb2RlIHJlcXVpcmVkIHRvIGFjdGl2YXRlIGJpbmRpbmcuCiAgICBwdWIgbW9kZTogQmluZGluZ01vZGUsCgogICAgLy8vIEV4Y2x1ZGVkIGJpbmRpbmcgbW9kZXMgd2hlcmUgdGhlIGJpbmRpbmcgd29uJ3QgYmUgYWN0aXZhdGVkLgogICAgcHViIG5vdG1vZGU6IEJpbmRpbmdNb2RlLAoKICAgIC8vLyBUaGlzIHByb3BlcnR5IGlzIHVzZWQgYXMgcGFydCBvZiB0aGUgdHJpZ2dlciBkZXRlY3Rpb24gY29kZS4KICAgIC8vLwogICAgLy8vIEZvciBleGFtcGxlLCB0aGlzIG1pZ2h0IGJlIGEga2V5IGxpa2UgIkciLCBvciBhIG1vdXNlIGJ1dHRvbi4KICAgIHB1YiB0cmlnZ2VyOiBULAp9CgppbXBsPFQ6IEVxPiBCaW5kaW5nPFQ+IHsKICAgICNbaW5saW5lXQogICAgcHViIGZuIGlzX3RyaWdnZXJlZF9ieSgKICAgICAgICAmc2VsZiwKICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZSwKICAgICAgICBtb2RzOiBNb2RpZmllcnNTdGF0ZSwKICAgICAgICBpbnB1dDogJlQsCiAgICApIC0+IGJvb2wgewogICAgICAgIC8vIENoZWNrIGlucHV0IGZpcnN0IHNpbmNlIGJpbmRpbmdzIGFyZSBzdG9yZWQgaW4gb25lIGJpZyBsaXN0LiBUaGlzIGlzCiAgICAgICAgLy8gdGhlIG1vc3QgbGlrZWx5IGl0ZW0gdG8gZmFpbCBzbyBwcmlvcml0aXppbmcgaXQgaGVyZSBhbGxvd3MgbW9yZQogICAgICAgIC8vIGNoZWNrcyB0byBiZSBzaG9ydCBjaXJjdWl0ZWQuCiAgICAgICAgc2VsZi50cmlnZ2VyID09ICppbnB1dAogICAgICAgICAgICAmJiBzZWxmLm1vZHMgPT0gbW9kcwogICAgICAgICAgICAmJiBtb2RlLmNvbnRhaW5zKHNlbGYubW9kZS5jbG9uZSgpKQogICAgICAgICAgICAmJiAhbW9kZS5pbnRlcnNlY3RzKHNlbGYubm90bW9kZS5jbG9uZSgpKQogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHRyaWdnZXJzX21hdGNoKCZzZWxmLCBiaW5kaW5nOiAmQmluZGluZzxUPikgLT4gYm9vbCB7CiAgICAgICAgLy8gQ2hlY2sgdGhlIGJpbmRpbmcncyBrZXkgYW5kIG1vZGlmaWVycy4KICAgICAgICBpZiBzZWxmLnRyaWdnZXIgIT0gYmluZGluZy50cmlnZ2VyIHx8IHNlbGYubW9kcyAhPSBiaW5kaW5nLm1vZHMgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICBsZXQgc2VsZm1vZGUgPSBpZiBzZWxmLm1vZGUuaXNfZW1wdHkoKSB7CiAgICAgICAgICAgIEJpbmRpbmdNb2RlOjphbGwoKQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHNlbGYubW9kZS5jbG9uZSgpCiAgICAgICAgfTsKICAgICAgICBsZXQgYmluZGluZ21vZGUgPSBpZiBiaW5kaW5nLm1vZGUuaXNfZW1wdHkoKSB7CiAgICAgICAgICAgIEJpbmRpbmdNb2RlOjphbGwoKQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJpbmRpbmcubW9kZS5jbG9uZSgpCiAgICAgICAgfTsKCiAgICAgICAgaWYgIXNlbGZtb2RlLmludGVyc2VjdHMoYmluZGluZ21vZGUpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgLy8gVGhlIGJpbmRpbmdzIGFyZSBuZXZlciBhY3RpdmUgYXQgdGhlIHNhbWUgdGltZSB3aGVuIHRoZSByZXF1aXJlZCBtb2RlcyBvZiBvbmUgYmluZGluZwogICAgICAgIC8vIGFyZSBwYXJ0IG9mIHRoZSBmb3JiaWRkZW4gYmluZGluZ3Mgb2YgdGhlIG90aGVyLgogICAgICAgIGlmIHNlbGYubW9kZS5pbnRlcnNlY3RzKGJpbmRpbmcubm90bW9kZS5jbG9uZSgpKQogICAgICAgICAgICB8fCBiaW5kaW5nLm1vZGUuaW50ZXJzZWN0cyhzZWxmLm5vdG1vZGUuY2xvbmUoKSkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIHRydWUKICAgIH0KfQoKI1tkZXJpdmUoQ2xvbmUsIERlYnVnLCBFcSwgUGFydGlhbEVxLCBIYXNoKV0KcHViIGVudW0gQmluZGluZ0tleSB7CiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBTY2FuY29kZShQaHlzaWNhbEtleSksCiAgICBLZXljb2RlIHsKICAgICAgICBrZXk6IEtleSwKICAgICAgICBsb2NhdGlvbjogS2V5TG9jYXRpb24sCiAgICB9LAp9CgpwdWIgdHlwZSBLZXlCaW5kaW5nID0gQmluZGluZzxCaW5kaW5nS2V5PjsKcHViIHR5cGUgS2V5QmluZGluZ3MgPSBWZWM8S2V5QmluZGluZz47CgovLy8gQmluZGluZ3MgdGhhdCBhcmUgdHJpZ2dlcmVkIGJ5IGEgbW91c2UgYnV0dG9uLgpwdWIgdHlwZSBNb3VzZUJpbmRpbmcgPSBCaW5kaW5nPE1vdXNlQnV0dG9uPjsKCmJpdGZsYWdzISB7CiAgICAvLy8gTW9kZXMgYXZhaWxhYmxlIGZvciBrZXkgYmluZGluZ3MuCiAgICAjW2Rlcml2ZShDbG9uZSwgRGVidWcsIEVxLCBQYXJ0aWFsRXEpXQogICAgcHViIHN0cnVjdCBCaW5kaW5nTW9kZTogdTggewogICAgICAgIGNvbnN0IEFQUF9DVVJTT1IgICAgICAgICAgPSAwYjAwMDBfMDAwMTsKICAgICAgICBjb25zdCBBUFBfS0VZUEFEICAgICAgICAgID0gMGIwMDAwXzAwMTA7CiAgICAgICAgY29uc3QgQUxUX1NDUkVFTiAgICAgICAgICA9IDBiMDAwMF8wMTAwOwogICAgICAgIGNvbnN0IFZJICAgICAgICAgICAgICAgICAgPSAwYjAwMDBfMTAwMDsKICAgICAgICBjb25zdCBTRUFSQ0ggICAgICAgICAgICAgID0gMGIwMDAxXzAwMDA7CiAgICAgICAgY29uc3QgRElTQU1CSUdVQVRFX0tFWVMgICA9IDBiMDAxMF8wMDAwOwogICAgICAgIGNvbnN0IEFMTF9LRVlTX0FTX0VTQyAgICAgPSAwYjAxMDBfMDAwMDsKICAgIH0KfQoKaW1wbCBCaW5kaW5nTW9kZSB7CiAgICBwdWIgZm4gbmV3KG1vZGU6ICZNb2RlLCBzZWFyY2g6IGJvb2wpIC0+IEJpbmRpbmdNb2RlIHsKICAgICAgICBsZXQgbXV0IGJpbmRpbmdfbW9kZSA9IEJpbmRpbmdNb2RlOjplbXB0eSgpOwogICAgICAgIGJpbmRpbmdfbW9kZS5zZXQoQmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIG1vZGUuY29udGFpbnMoTW9kZTo6QVBQX0NVUlNPUikpOwogICAgICAgIGJpbmRpbmdfbW9kZS5zZXQoQmluZGluZ01vZGU6OkFQUF9LRVlQQUQsIG1vZGUuY29udGFpbnMoTW9kZTo6QVBQX0tFWVBBRCkpOwogICAgICAgIGJpbmRpbmdfbW9kZS5zZXQoQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sIG1vZGUuY29udGFpbnMoTW9kZTo6QUxUX1NDUkVFTikpOwogICAgICAgIGJpbmRpbmdfbW9kZS5zZXQoQmluZGluZ01vZGU6OlNFQVJDSCwgc2VhcmNoKTsKICAgICAgICBiaW5kaW5nX21vZGUuc2V0KAogICAgICAgICAgICBCaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVMsCiAgICAgICAgICAgIG1vZGUuY29udGFpbnMoTW9kZTo6RElTQU1CSUdVQVRFX0VTQ19DT0RFUyksCiAgICAgICAgKTsKICAgICAgICBiaW5kaW5nX21vZGUuc2V0KAogICAgICAgICAgICBCaW5kaW5nTW9kZTo6QUxMX0tFWVNfQVNfRVNDLAogICAgICAgICAgICBtb2RlLmNvbnRhaW5zKE1vZGU6OlJFUE9SVF9BTExfS0VZU19BU19FU0MpLAogICAgICAgICk7CiAgICAgICAgYmluZGluZ19tb2RlLnNldChCaW5kaW5nTW9kZTo6VkksIG1vZGUuY29udGFpbnMoTW9kZTo6VkkpKTsKICAgICAgICBiaW5kaW5nX21vZGUKICAgIH0KfQoKI1tkZXJpdmUoRGVidWcsIENsb25lLCBFcSwgUGFydGlhbEVxKV0KI1thbGxvdyh1bnVzZWQpXQpwdWIgZW51bSBQcm9ncmFtIHsKICAgIEp1c3QoU3RyaW5nKSwKICAgIFdpdGhBcmdzIHsgcHJvZ3JhbTogU3RyaW5nLCBhcmdzOiBWZWM8U3RyaW5nPiB9LAp9CgppbXBsIFByb2dyYW0gewogICAgcHViIGZuIHByb2dyYW0oJnNlbGYpIC0+ICZzdHIgewogICAgICAgIG1hdGNoIHNlbGYgewogICAgICAgICAgICBQcm9ncmFtOjpKdXN0KHByb2dyYW0pID0+IHByb2dyYW0sCiAgICAgICAgICAgIFByb2dyYW06OldpdGhBcmdzIHsgcHJvZ3JhbSwgLi4gfSA9PiBwcm9ncmFtLAogICAgICAgIH0KICAgIH0KCiAgICBwdWIgZm4gYXJncygmc2VsZikgLT4gJltTdHJpbmddIHsKICAgICAgICBtYXRjaCBzZWxmIHsKICAgICAgICAgICAgUHJvZ3JhbTo6SnVzdChfKSA9PiAmW10sCiAgICAgICAgICAgIFByb2dyYW06OldpdGhBcmdzIHsgYXJncywgLi4gfSA9PiBhcmdzLAogICAgICAgIH0KICAgIH0KfQoKaW1wbCBGcm9tPFN0cmluZz4gZm9yIEFjdGlvbiB7CiAgICBmbiBmcm9tKGFjdGlvbjogU3RyaW5nKSAtPiBBY3Rpb24gewogICAgICAgIGxldCBhY3Rpb24gPSBhY3Rpb24udG9fbG93ZXJjYXNlKCk7CgogICAgICAgIGxldCBhY3Rpb25fZnJvbV9zdHJpbmcgPSBtYXRjaCBhY3Rpb24uYXNfc3RyKCkgewogICAgICAgICAgICAicGFzdGUiID0+IFNvbWUoQWN0aW9uOjpQYXN0ZSksCiAgICAgICAgICAgICJxdWl0IiA9PiBTb21lKEFjdGlvbjo6UXVpdCksCiAgICAgICAgICAgICJjb3B5IiA9PiBTb21lKEFjdGlvbjo6Q29weSksCiAgICAgICAgICAgICJzZWFyY2hmb3J3YXJkIiA9PiBTb21lKEFjdGlvbjo6U2VhcmNoRm9yd2FyZCksCiAgICAgICAgICAgICJzZWFyY2hiYWNrd2FyZCIgPT4gU29tZShBY3Rpb246OlNlYXJjaEJhY2t3YXJkKSwKICAgICAgICAgICAgInNlYXJjaGNvbmZpcm0iID0+IFNvbWUoQWN0aW9uOjpTZWFyY2goU2VhcmNoQWN0aW9uOjpTZWFyY2hDb25maXJtKSksCiAgICAgICAgICAgICJzZWFyY2hjYW5jZWwiID0+IFNvbWUoQWN0aW9uOjpTZWFyY2goU2VhcmNoQWN0aW9uOjpTZWFyY2hDYW5jZWwpKSwKICAgICAgICAgICAgInNlYXJjaGNsZWFyIiA9PiBTb21lKEFjdGlvbjo6U2VhcmNoKFNlYXJjaEFjdGlvbjo6U2VhcmNoQ2xlYXIpKSwKICAgICAgICAgICAgInNlYXJjaGZvY3VzbmV4dCIgPT4gU29tZShBY3Rpb246OlNlYXJjaChTZWFyY2hBY3Rpb246OlNlYXJjaEZvY3VzTmV4dCkpLAogICAgICAgICAgICAic2VhcmNoZm9jdXNwcmV2aW91cyIgPT4gewogICAgICAgICAgICAgICAgU29tZShBY3Rpb246OlNlYXJjaChTZWFyY2hBY3Rpb246OlNlYXJjaEZvY3VzUHJldmlvdXMpKQogICAgICAgICAgICB9CiAgICAgICAgICAgICJzZWFyY2hkZWxldGV3b3JkIiA9PiBTb21lKEFjdGlvbjo6U2VhcmNoKFNlYXJjaEFjdGlvbjo6U2VhcmNoRGVsZXRlV29yZCkpLAogICAgICAgICAgICAic2VhcmNoaGlzdG9yeW5leHQiID0+IFNvbWUoQWN0aW9uOjpTZWFyY2goU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dCkpLAogICAgICAgICAgICAic2VhcmNoaGlzdG9yeXByZXZpb3VzIiA9PiB7CiAgICAgICAgICAgICAgICBTb21lKEFjdGlvbjo6U2VhcmNoKFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeVByZXZpb3VzKSkKICAgICAgICAgICAgfQogICAgICAgICAgICAiY2xlYXJoaXN0b3J5IiA9PiBTb21lKEFjdGlvbjo6Q2xlYXJIaXN0b3J5KSwKICAgICAgICAgICAgInJlc2V0Zm9udHNpemUiID0+IFNvbWUoQWN0aW9uOjpSZXNldEZvbnRTaXplKSwKICAgICAgICAgICAgImluY3JlYXNlZm9udHNpemUiID0+IFNvbWUoQWN0aW9uOjpJbmNyZWFzZUZvbnRTaXplKSwKICAgICAgICAgICAgImRlY3JlYXNlZm9udHNpemUiID0+IFNvbWUoQWN0aW9uOjpEZWNyZWFzZUZvbnRTaXplKSwKICAgICAgICAgICAgImNyZWF0ZXdpbmRvdyIgPT4gU29tZShBY3Rpb246OldpbmRvd0NyZWF0ZU5ldyksCiAgICAgICAgICAgICJjcmVhdGV0YWIiID0+IFNvbWUoQWN0aW9uOjpUYWJDcmVhdGVOZXcpLAogICAgICAgICAgICAiY2xvc2V0YWIiID0+IFNvbWUoQWN0aW9uOjpUYWJDbG9zZUN1cnJlbnQpLAogICAgICAgICAgICAiY2xvc2VjdXJyZW50dGFib3JzcGxpdCIgPT4gU29tZShBY3Rpb246OkNsb3NlQ3VycmVudFNwbGl0T3JUYWIpLAogICAgICAgICAgICAiY2xvc2V1bmZvY3VzZWR0YWJzIiA9PiBTb21lKEFjdGlvbjo6VGFiQ2xvc2VVbmZvY3VzZWQpLAogICAgICAgICAgICAib3BlbmNvbmZpZ2VkaXRvciIgPT4gU29tZShBY3Rpb246OkNvbmZpZ0VkaXRvciksCiAgICAgICAgICAgICJzZWxlY3RwcmV2dGFiIiA9PiBTb21lKEFjdGlvbjo6U2VsZWN0UHJldlRhYiksCiAgICAgICAgICAgICJzZWxlY3RuZXh0dGFiIiA9PiBTb21lKEFjdGlvbjo6U2VsZWN0TmV4dFRhYiksCiAgICAgICAgICAgICJzZWxlY3RsYXN0dGFiIiA9PiBTb21lKEFjdGlvbjo6U2VsZWN0TGFzdFRhYiksCiAgICAgICAgICAgICJyZWNlaXZlY2hhciIgPT4gU29tZShBY3Rpb246OlJlY2VpdmVDaGFyKSwKICAgICAgICAgICAgInNjcm9sbGhhbGZwYWdldXAiID0+IFNvbWUoQWN0aW9uOjpTY3JvbGxIYWxmUGFnZVVwKSwKICAgICAgICAgICAgInNjcm9sbGhhbGZwYWdlZG93biIgPT4gU29tZShBY3Rpb246OlNjcm9sbEhhbGZQYWdlRG93biksCiAgICAgICAgICAgICJzY3JvbGx0b3RvcCIgPT4gU29tZShBY3Rpb246OlNjcm9sbFRvVG9wKSwKICAgICAgICAgICAgInNjcm9sbHRvYm90dG9tIiA9PiBTb21lKEFjdGlvbjo6U2Nyb2xsVG9Cb3R0b20pLAogICAgICAgICAgICAic3BsaXRyaWdodCIgPT4gU29tZShBY3Rpb246OlNwbGl0UmlnaHQpLAogICAgICAgICAgICAic3BsaXRkb3duIiA9PiBTb21lKEFjdGlvbjo6U3BsaXREb3duKSwKICAgICAgICAgICAgInNlbGVjdG5leHRzcGxpdCIgPT4gU29tZShBY3Rpb246OlNlbGVjdE5leHRTcGxpdCksCiAgICAgICAgICAgICJzZWxlY3RwcmV2c3BsaXQiID0+IFNvbWUoQWN0aW9uOjpTZWxlY3RQcmV2U3BsaXQpLAogICAgICAgICAgICAidG9nZ2xldmltb2RlIiA9PiBTb21lKEFjdGlvbjo6VG9nZ2xlVmlNb2RlKSwKICAgICAgICAgICAgInRvZ2dsZWZ1bGxzY3JlZW4iID0+IFNvbWUoQWN0aW9uOjpUb2dnbGVGdWxsc2NyZWVuKSwKICAgICAgICAgICAgIm5vbmUiID0+IFNvbWUoQWN0aW9uOjpOb25lKSwKICAgICAgICAgICAgXyA9PiBOb25lLAogICAgICAgIH07CgogICAgICAgIGlmIGFjdGlvbl9mcm9tX3N0cmluZy5pc19zb21lKCkgewogICAgICAgICAgICByZXR1cm4gYWN0aW9uX2Zyb21fc3RyaW5nLnVud3JhcF9vcihBY3Rpb246Ok5vbmUpOwogICAgICAgIH0KCiAgICAgICAgbGV0IHJlID0gcmVnZXg6OlJlZ2V4OjpuZXcociJzZWxlY3R0YWJcKChbXigpXSspXCkiKS51bndyYXAoKTsKICAgICAgICBmb3IgY2FwdHVyZSBpbiByZS5jYXB0dXJlc19pdGVyKCZhY3Rpb24pIHsKICAgICAgICAgICAgaWYgbGV0IFNvbWUobWF0Y2hlZCkgPSBjYXB0dXJlLmdldCgxKSB7CiAgICAgICAgICAgICAgICBsZXQgbWF0Y2hlZF9zdHJpbmcgPSBtYXRjaGVkLmFzX3N0cigpLnRvX3N0cmluZygpOwogICAgICAgICAgICAgICAgbGV0IHBhcnNlZF9tYXRjaGVkX3N0cmluZzogdXNpemUgPSBtYXRjaGVkX3N0cmluZy5wYXJzZSgpLnVud3JhcF9vcigwKTsKICAgICAgICAgICAgICAgIHJldHVybiBBY3Rpb246OlNlbGVjdFRhYihwYXJzZWRfbWF0Y2hlZF9zdHJpbmcpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBsZXQgcmUgPSByZWdleDo6UmVnZXg6Om5ldyhyInJ1blwoKFteKCldKylcKSIpLnVud3JhcCgpOwogICAgICAgIGZvciBjYXB0dXJlIGluIHJlLmNhcHR1cmVzX2l0ZXIoJmFjdGlvbikgewogICAgICAgICAgICBpZiBsZXQgU29tZShtYXRjaGVkKSA9IGNhcHR1cmUuZ2V0KDEpIHsKICAgICAgICAgICAgICAgIGxldCBtYXRjaGVkX3N0cmluZyA9IG1hdGNoZWQuYXNfc3RyKCkudG9fc3RyaW5nKCk7CiAgICAgICAgICAgICAgICBpZiBtYXRjaGVkX3N0cmluZy5jb250YWlucygnICcpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgbXV0IHZlY19wcm9ncmFtX3dpdGhfYXJnczogVmVjPFN0cmluZz4gPQogICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVkX3N0cmluZy5zcGxpdCgnICcpLm1hcCh8c3wgcy50b19zdHJpbmcoKSkuY29sbGVjdCgpOwogICAgICAgICAgICAgICAgICAgIGlmIHZlY19wcm9ncmFtX3dpdGhfYXJncy5pc19lbXB0eSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICBsZXQgcHJvZ3JhbSA9IHZlY19wcm9ncmFtX3dpdGhfYXJnc1swXS50b19zdHJpbmcoKTsKICAgICAgICAgICAgICAgICAgICB2ZWNfcHJvZ3JhbV93aXRoX2FyZ3MucmVtb3ZlKDApOwoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gQWN0aW9uOjpSdW4oUHJvZ3JhbTo6V2l0aEFyZ3MgewogICAgICAgICAgICAgICAgICAgICAgICBwcm9ncmFtLAogICAgICAgICAgICAgICAgICAgICAgICBhcmdzOiB2ZWNfcHJvZ3JhbV93aXRoX2FyZ3MsCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBBY3Rpb246OlJ1bihQcm9ncmFtOjpKdXN0KG1hdGNoZWRfc3RyaW5nKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGxldCByZSA9IHJlZ2V4OjpSZWdleDo6bmV3KHIic2Nyb2xsXCgoW14oKV0rKVwpIikudW53cmFwKCk7CiAgICAgICAgZm9yIGNhcHR1cmUgaW4gcmUuY2FwdHVyZXNfaXRlcigmYWN0aW9uKSB7CiAgICAgICAgICAgIGlmIGxldCBTb21lKG1hdGNoZWQpID0gY2FwdHVyZS5nZXQoMSkgewogICAgICAgICAgICAgICAgbGV0IG1hdGNoZWRfc3RyaW5nID0gbWF0Y2hlZC5hc19zdHIoKS50b19zdHJpbmcoKTsKICAgICAgICAgICAgICAgIGxldCBwYXJzZWRfbWF0Y2hlZF9zdHJpbmc6IGkzMiA9IG1hdGNoZWRfc3RyaW5nLnBhcnNlKCkudW53cmFwX29yKDEpOwogICAgICAgICAgICAgICAgcmV0dXJuIEFjdGlvbjo6U2Nyb2xsKHBhcnNlZF9tYXRjaGVkX3N0cmluZyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIEFjdGlvbjo6Tm9uZQogICAgfQp9CgojW2Rlcml2ZShEZWJ1ZywgQ2xvbmUsIFBhcnRpYWxFcSwgRXEpXQpwdWIgZW51bSBBY3Rpb24gewogICAgLy8vIFdyaXRlIGFuIGVzY2FwZSBzZXF1ZW5jZS4KICAgIEVzYyhTdHJpbmcpLAoKICAgIC8vLyBSdW4gZ2l2ZW4gY29tbWFuZC4KICAgIFJ1bihQcm9ncmFtKSwKCiAgICAvLy8gU2Nyb2xsCiAgICBTY3JvbGwoaTMyKSwKCiAgICAvLyBSZWdleCBrZXlib2FyZCBoaW50cy4KICAgIC8vIEhpbnQoSGludCksCgogICAgLy8gTW92ZSB2aSBtb2RlIGN1cnNvci4KICAgIFZpTW90aW9uKFZpTW90aW9uKSwKCiAgICAvLyBQZXJmb3JtIHZpIG1vZGUgYWN0aW9uLgogICAgVmkoVmlBY3Rpb24pLAogICAgLy8vIFBlcmZvcm0gbW91c2UgYmluZGluZyBleGNsdXNpdmUgYWN0aW9uLgogICAgTW91c2UoTW91c2VBY3Rpb24pLAoKICAgIC8vLyBQYXN0ZSBjb250ZW50cyBvZiBzeXN0ZW0gY2xpcGJvYXJkLgogICAgUGFzdGUsCgogICAgLy8vIFN0b3JlIGN1cnJlbnQgc2VsZWN0aW9uIGludG8gY2xpcGJvYXJkLgogICAgQ29weSwKCiAgICAjW2NmZyhub3QoYW55KHRhcmdldF9vcyA9ICJtYWNvcyIsIHdpbmRvd3MpKSldCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICAvLy8gU3RvcmUgY3VycmVudCBzZWxlY3Rpb24gaW50byBzZWxlY3Rpb24gYnVmZmVyLgogICAgQ29weVNlbGVjdGlvbiwKCiAgICAvLy8gUGFzdGUgY29udGVudHMgb2Ygc2VsZWN0aW9uIGJ1ZmZlci4KICAgIFBhc3RlU2VsZWN0aW9uLAoKICAgIC8vLyBJbmNyZWFzZSBmb250IHNpemUuCiAgICBJbmNyZWFzZUZvbnRTaXplLAoKICAgIC8vLyBEZWNyZWFzZSBmb250IHNpemUuCiAgICBEZWNyZWFzZUZvbnRTaXplLAoKICAgIC8vLyBSZXNldCBmb250IHNpemUgdG8gdGhlIGNvbmZpZyB2YWx1ZS4KICAgIFJlc2V0Rm9udFNpemUsCgogICAgLy8vIFNjcm9sbCBleGFjdGx5IG9uZSBwYWdlIHVwLgogICAgU2Nyb2xsUGFnZVVwLAoKICAgIC8vLyBTY3JvbGwgZXhhY3RseSBvbmUgcGFnZSBkb3duLgogICAgU2Nyb2xsUGFnZURvd24sCgogICAgLy8vIFNjcm9sbCBoYWxmIGEgcGFnZSB1cC4KICAgIFNjcm9sbEhhbGZQYWdlVXAsCgogICAgLy8vIFNjcm9sbCBoYWxmIGEgcGFnZSBkb3duLgogICAgU2Nyb2xsSGFsZlBhZ2VEb3duLAoKICAgIC8vLyBTY3JvbGwgYWxsIHRoZSB3YXkgdG8gdGhlIHRvcC4KICAgIFNjcm9sbFRvVG9wLAoKICAgIC8vLyBTY3JvbGwgYWxsIHRoZSB3YXkgdG8gdGhlIGJvdHRvbS4KICAgIFNjcm9sbFRvQm90dG9tLAoKICAgIC8vLyBDbGVhciB0aGUgZGlzcGxheSBidWZmZXIocykgdG8gcmVtb3ZlIGhpc3RvcnkuCiAgICBDbGVhckhpc3RvcnksCgogICAgLy8vIEhpZGUgdGhlIFJpbyB3aW5kb3cuCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBIaWRlLAoKICAgIC8vLyBIaWRlIGFsbCB3aW5kb3dzIG90aGVyIHRoYW4gUmlvIG9uIG1hY09TLgogICAgI1tjZmcodGFyZ2V0X29zID0gIm1hY29zIildCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBIaWRlT3RoZXJBcHBsaWNhdGlvbnMsCgogICAgLy8vIE1pbmltaXplIHRoZSBSaW8gd2luZG93LgogICAgI1thbGxvdyhkZWFkX2NvZGUpXQogICAgTWluaW1pemUsCgogICAgLy8vIFF1aXQgUmlvLgogICAgUXVpdCwKCiAgICAvLy8gQ2xlYXIgd2FybmluZyBhbmQgZXJyb3Igbm90aWNlcy4KICAgIENsZWFyTG9nTm90aWNlLAoKICAgIC8vLyBTcGF3biBhIG5ldyBpbnN0YW5jZSBvZiBSaW8uCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBTcGF3bk5ld0luc3RhbmNlLAoKICAgIC8vLyBDcmVhdGUgYSBuZXcgUmlvIHdpbmRvdy4KICAgICNbYWxsb3coZGVhZF9jb2RlKV0KICAgIFdpbmRvd0NyZWF0ZU5ldywKCiAgICAvLy8gQ3JlYXRlIGNvbmZpZyBlZGl0b3IuCiAgICBDb25maWdFZGl0b3IsCgogICAgLy8vIENyZWF0ZSBhIG5ldyBSaW8gdGFiLgogICAgVGFiQ3JlYXRlTmV3LAoKICAgIC8vLyBTd2l0Y2ggdG8gbmV4dCB0YWIuCiAgICBTZWxlY3ROZXh0VGFiLAoKICAgIC8vLyBTd2l0Y2ggdG8gcHJldiB0YWIuCiAgICBTZWxlY3RQcmV2VGFiLAoKICAgIC8vLyBDbG9zZSB0YWIuCiAgICBUYWJDbG9zZUN1cnJlbnQsCgogICAgQ2xvc2VDdXJyZW50U3BsaXRPclRhYiwKCiAgICAvLy8gQ2xvc2UgYWxsIG90aGVyIHRhYnMgKGxlYXZlIG9ubHkgdGhlIGN1cnJlbnQgdGFiKS4KICAgIFRhYkNsb3NlVW5mb2N1c2VkLAoKICAgIC8vLyBUb2dnbGUgZnVsbHNjcmVlbi4KICAgICNbYWxsb3coZGVhZF9jb2RlKV0KICAgIFRvZ2dsZUZ1bGxzY3JlZW4sCgogICAgLy8vIFRvZ2dsZSBtYXhpbWl6ZWQuCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBUb2dnbGVNYXhpbWl6ZWQsCgogICAgLy8vIFRvZ2dsZSBzaW1wbGUgZnVsbHNjcmVlbiBvbiBtYWNPUy4KICAgICNbY2ZnKHRhcmdldF9vcyA9ICJtYWNvcyIpXQogICAgI1thbGxvdyhkZWFkX2NvZGUpXQogICAgVG9nZ2xlU2ltcGxlRnVsbHNjcmVlbiwKCiAgICAvLy8gQ2xlYXIgYWN0aXZlIHNlbGVjdGlvbi4KICAgIENsZWFyU2VsZWN0aW9uLAoKICAgIC8vLyBUb2dnbGUgdmkgbW9kZS4KICAgIFRvZ2dsZVZpTW9kZSwKCiAgICAvLyBUYWIgc2VsZWN0aW9ucwogICAgU2VsZWN0VGFiKHVzaXplKSwKICAgIFNlbGVjdExhc3RUYWIsCgogICAgU2VhcmNoKFNlYXJjaEFjdGlvbiksCiAgICAvLy8gU3RhcnQgYSBmb3J3YXJkIGJ1ZmZlciBzZWFyY2guCiAgICBTZWFyY2hGb3J3YXJkLAoKICAgIC8vLyBTdGFydCBhIGJhY2t3YXJkIGJ1ZmZlciBzZWFyY2guCiAgICBTZWFyY2hCYWNrd2FyZCwKCiAgICAvLy8gU3BsaXQgaG9yaXpvbnRhbGx5CiAgICBTcGxpdFJpZ2h0LAoKICAgIC8vLyBTcGxpdCB2ZXJ0aWNhbGx5CiAgICBTcGxpdERvd24sCgogICAgU2VsZWN0TmV4dFNwbGl0LAogICAgU2VsZWN0UHJldlNwbGl0LAoKICAgIC8vLyBBbGxvdyByZWNlaXZpbmcgY2hhciBpbnB1dC4KICAgIFJlY2VpdmVDaGFyLAoKICAgIC8vLyBObyBhY3Rpb24uCiAgICBOb25lLAp9CgppbXBsIEZyb208JidzdGF0aWMgc3RyPiBmb3IgQWN0aW9uIHsKICAgIGZuIGZyb20oczogJidzdGF0aWMgc3RyKSAtPiBBY3Rpb24gewogICAgICAgIEFjdGlvbjo6RXNjKHMuaW50bygpKQogICAgfQp9CgppbXBsIEZyb208VmlNb3Rpb24+IGZvciBBY3Rpb24gewogICAgZm4gZnJvbShtb3Rpb246IFZpTW90aW9uKSAtPiBTZWxmIHsKICAgICAgICBTZWxmOjpWaU1vdGlvbihtb3Rpb24pCiAgICB9Cn0KCmltcGwgRnJvbTxWaUFjdGlvbj4gZm9yIEFjdGlvbiB7CiAgICBmbiBmcm9tKGFjdGlvbjogVmlBY3Rpb24pIC0+IFNlbGYgewogICAgICAgIFNlbGY6OlZpKGFjdGlvbikKICAgIH0KfQoKLy8vIFZpIG1vZGUgc3BlY2lmaWMgYWN0aW9ucy4KI1tkZXJpdmUoRGVidWcsIENvcHksIENsb25lLCBQYXJ0aWFsRXEsIEVxKV0KcHViIGVudW0gVmlBY3Rpb24gewogICAgLy8vIFRvZ2dsZSBub3JtYWwgdmkgc2VsZWN0aW9uLgogICAgVG9nZ2xlTm9ybWFsU2VsZWN0aW9uLAogICAgLy8vIFRvZ2dsZSBsaW5lIHZpIHNlbGVjdGlvbi4KICAgIFRvZ2dsZUxpbmVTZWxlY3Rpb24sCiAgICAvLy8gVG9nZ2xlIGJsb2NrIHZpIHNlbGVjdGlvbi4KICAgIFRvZ2dsZUJsb2NrU2VsZWN0aW9uLAogICAgLy8vIFRvZ2dsZSBzZW1hbnRpYyB2aSBzZWxlY3Rpb24uCiAgICBUb2dnbGVTZW1hbnRpY1NlbGVjdGlvbiwKICAgIC8vLyBDZW50ZXJzIHRoZSBzY3JlZW4gYXJvdW5kIHRoZSB2aSBtb2RlIGN1cnNvci4KICAgIENlbnRlckFyb3VuZFZpQ3Vyc29yLAp9CgptYWNyb19ydWxlcyEgYmluZGluZ3MgewogICAgKAogICAgICAgICR0eTppZGVudDsKICAgICAgICAkKAogICAgICAgICAgICAka2V5OmV4cHIKICAgICAgICAgICAgJCg9PiRsb2NhdGlvbjpleHByKT8KICAgICAgICAgICAgJCgsJG1vZHM6ZXhwcikqCiAgICAgICAgICAgICQoLCskbW9kZTpleHByKSoKICAgICAgICAgICAgJCgsfiRub3Rtb2RlOmV4cHIpKgogICAgICAgICAgICA7JGFjdGlvbjpleHByCiAgICAgICAgKTsqCiAgICAgICAgJCg7KSoKICAgICkgPT4ge3sKICAgICAgICBsZXQgbXV0IHYgPSBWZWM6Om5ldygpOwoKICAgICAgICAkKAogICAgICAgICAgICBsZXQgbXV0IF9tb2RzID0gTW9kaWZpZXJzU3RhdGU6OmVtcHR5KCk7CiAgICAgICAgICAgICQoX21vZHMgPSAkbW9kczspKgogICAgICAgICAgICBsZXQgbXV0IF9tb2RlID0gQmluZGluZ01vZGU6OmVtcHR5KCk7CiAgICAgICAgICAgICQoX21vZGUuaW5zZXJ0KCRtb2RlKTspKgogICAgICAgICAgICBsZXQgbXV0IF9ub3Rtb2RlID0gQmluZGluZ01vZGU6OmVtcHR5KCk7CiAgICAgICAgICAgICQoX25vdG1vZGUuaW5zZXJ0KCRub3Rtb2RlKTspKgoKICAgICAgICAgICAgdi5wdXNoKCR0eSB7CiAgICAgICAgICAgICAgICB0cmlnZ2VyOiB0cmlnZ2VyISgkdHksICRrZXksICQoJGxvY2F0aW9uKT8pLAogICAgICAgICAgICAgICAgbW9kczogX21vZHMsCiAgICAgICAgICAgICAgICBtb2RlOiBfbW9kZSwKICAgICAgICAgICAgICAgIG5vdG1vZGU6IF9ub3Rtb2RlLAogICAgICAgICAgICAgICAgYWN0aW9uOiAkYWN0aW9uLmludG8oKSwKICAgICAgICAgICAgfSk7CiAgICAgICAgKSoKCiAgICAgICAgdgogICAgfX07Cn0KCm1hY3JvX3J1bGVzISB0cmlnZ2VyIHsKICAgIChLZXlCaW5kaW5nLCAka2V5OmxpdGVyYWwsICRsb2NhdGlvbjpleHByKSA9PiB7ewogICAgICAgIEJpbmRpbmdLZXk6OktleWNvZGUgewogICAgICAgICAgICBrZXk6IENoYXJhY3Rlcigka2V5LmludG8oKSksCiAgICAgICAgICAgIGxvY2F0aW9uOiAkbG9jYXRpb24sCiAgICAgICAgfQogICAgfX07CiAgICAoS2V5QmluZGluZywgJGtleTpsaXRlcmFsLCkgPT4ge3sKICAgICAgICBCaW5kaW5nS2V5OjpLZXljb2RlIHsKICAgICAgICAgICAga2V5OiBDaGFyYWN0ZXIoJGtleS5pbnRvKCkpLAogICAgICAgICAgICBsb2NhdGlvbjogS2V5TG9jYXRpb246OlN0YW5kYXJkLAogICAgICAgIH0KICAgIH19OwogICAgKEtleUJpbmRpbmcsICRrZXk6ZXhwciwpID0+IHt7CiAgICAgICAgQmluZGluZ0tleTo6S2V5Y29kZSB7CiAgICAgICAgICAgIGtleTogJGtleSwKICAgICAgICAgICAgbG9jYXRpb246IEtleUxvY2F0aW9uOjpTdGFuZGFyZCwKICAgICAgICB9CiAgICB9fTsKICAgICgkdHk6aWRlbnQsICRrZXk6ZXhwciwpID0+IHt7CiAgICAgICAgJGtleQogICAgfX07Cn0KCnB1YiBmbiBkZWZhdWx0X21vdXNlX2JpbmRpbmdzKCkgLT4gVmVjPE1vdXNlQmluZGluZz4gewogICAgYmluZGluZ3MhKAogICAgICAgIE1vdXNlQmluZGluZzsKICAgICAgICBNb3VzZUJ1dHRvbjo6UmlnaHQ7ICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1vdXNlQWN0aW9uOjpFeHBhbmRTZWxlY3Rpb247CiAgICAgICAgTW91c2VCdXR0b246OlJpZ2h0LCAgIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyBNb3VzZUFjdGlvbjo6RXhwYW5kU2VsZWN0aW9uOwogICAgICAgIE1vdXNlQnV0dG9uOjpNaWRkbGUsIH5CaW5kaW5nTW9kZTo6Vkk7ICAgICAgICAgQWN0aW9uOjpQYXN0ZVNlbGVjdGlvbjsKICAgICkKfQoKcHViIGZuIGRlZmF1bHRfa2V5X2JpbmRpbmdzKAogICAgdW5wcm9jZXNzZWRfY29uZmlnX2tleV9iaW5kaW5nczogVmVjPENvbmZpZ0tleUJpbmRpbmc+LAogICAgdXNlX25hdmlnYXRpb25fa2V5X2JpbmRpbmdzOiBib29sLAogICAgdXNlX3NwbGl0czogYm9vbCwKICAgIGNvbmZpZ19rZXlib2FyZDogQ29uZmlnS2V5Ym9hcmQsCikgLT4gVmVjPEtleUJpbmRpbmc+IHsKICAgIGxldCBtdXQgYmluZGluZ3MgPSBiaW5kaW5ncyEoCiAgICAgICAgS2V5QmluZGluZzsKICAgICAgICBLZXk6Ok5hbWVkKENvcHkpOyAgQWN0aW9uOjpDb3B5OwogICAgICAgIEtleTo6TmFtZWQoQ29weSksICArQmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkNsZWFyU2VsZWN0aW9uOwogICAgICAgIEtleTo6TmFtZWQoUGFzdGUpLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlBhc3RlOwogICAgICAgIEtleTo6Q2hhcmFjdGVyKCJsIi5pbnRvKCkpLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgQWN0aW9uOjpDbGVhckxvZ05vdGljZTsKICAgICAgICAibCIsICBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpFc2MoIlx4MGMiLmludG8oKSk7CiAgICAgICAgS2V5OjpOYW1lZChUYWIpLCAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkVzYygiXHgxYltaIi5pbnRvKCkpOwogICAgICAgIEtleTo6TmFtZWQoSG9tZSksICAgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6QUxUX1NDUkVFTjsgQWN0aW9uOjpTY3JvbGxUb1RvcDsKICAgICAgICBLZXk6Ok5hbWVkKEVuZCksICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OkFMVF9TQ1JFRU47IEFjdGlvbjo6U2Nyb2xsVG9Cb3R0b207CiAgICAgICAgS2V5OjpOYW1lZChQYWdlVXApLCAgIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOOyBBY3Rpb246OlNjcm9sbFBhZ2VVcDsKICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VEb3duKSwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OkFMVF9TQ1JFRU47IEFjdGlvbjo6U2Nyb2xsUGFnZURvd247CiAgICAgICAgS2V5OjpOYW1lZChIb21lKSwgICtCaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgQWN0aW9uOjpFc2MoIlx4MWJPSCIuaW50bygpKTsKICAgICAgICBLZXk6Ok5hbWVkKEVuZCksICAgK0JpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICBBY3Rpb246OkVzYygiXHgxYk9GIi5pbnRvKCkpOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dVcCksICAgICtCaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgQWN0aW9uOjpFc2MoIlx4MWJPQSIuaW50bygpKTsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93RG93biksICArQmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgIEFjdGlvbjo6RXNjKCJceDFiT0IiLmludG8oKSk7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd1JpZ2h0KSwgK0JpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICBBY3Rpb246OkVzYygiXHgxYk9DIi5pbnRvKCkpOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dMZWZ0KSwgICtCaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgQWN0aW9uOjpFc2MoIlx4MWJPRCIuaW50bygpKTsKCiAgICAgICAgLy8gVkkgTW9kZQogICAgICAgIEtleTo6TmFtZWQoU3BhY2UpLCBNb2RpZmllcnNTdGF0ZTo6QUxUIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlRvZ2dsZVZpTW9kZTsKICAgICAgICAiLyIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNlYXJjaEZvcndhcmQ7CiAgICAgICAgIm4iLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hGb2N1c05leHQ7CiAgICAgICAgIm4iLCAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hGb2N1c1ByZXZpb3VzOwogICAgICAgIEtleTo6TmFtZWQoRW50ZXIpLCArQmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgU2VhcmNoQWN0aW9uOjpTZWFyY2hGb2N1c05leHQ7CiAgICAgICAgS2V5OjpOYW1lZChFbnRlciksICtCaW5kaW5nTW9kZTo6U0VBUkNILCArQmluZGluZ01vZGU6OlZJOyBTZWFyY2hBY3Rpb246OlNlYXJjaENvbmZpcm07CiAgICAgICAgS2V5OjpOYW1lZChFc2NhcGUpLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hDYW5jZWw7CiAgICAgICAgS2V5OjpOYW1lZChFbnRlciksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IFNlYXJjaEFjdGlvbjo6U2VhcmNoRm9jdXNQcmV2aW91czsKICAgICAgICAiaSIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlRvZ2dsZVZpTW9kZTsKICAgICAgICAiYyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlRvZ2dsZVZpTW9kZTsKICAgICAgICBLZXk6Ok5hbWVkKEVzY2FwZSksICtCaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6Q2xlYXJTZWxlY3Rpb247CiAgICAgICAgImkiLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTY3JvbGxUb0JvdHRvbTsKICAgICAgICAiZyIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNjcm9sbFRvVG9wOwogICAgICAgICJnIiwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTY3JvbGxUb0JvdHRvbTsKICAgICAgICAiYiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTY3JvbGxQYWdlVXA7CiAgICAgICAgImYiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6U2Nyb2xsUGFnZURvd247CiAgICAgICAgInUiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6U2Nyb2xsSGFsZlBhZ2VVcDsKICAgICAgICAiZCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTY3JvbGxIYWxmUGFnZURvd247CiAgICAgICAgInkiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNjcm9sbCgxKTsKICAgICAgICAiZSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6U2Nyb2xsKC0xKTsKICAgICAgICAieSIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkNvcHk7CiAgICAgICAgInkiLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpDbGVhclNlbGVjdGlvbjsKICAgICAgICAidiIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaUFjdGlvbjo6VG9nZ2xlTm9ybWFsU2VsZWN0aW9uOwogICAgICAgICJ2IiwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgVmlBY3Rpb246OlRvZ2dsZUxpbmVTZWxlY3Rpb247CiAgICAgICAgInYiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IFZpQWN0aW9uOjpUb2dnbGVCbG9ja1NlbGVjdGlvbjsKICAgICAgICAidiIsIE1vZGlmaWVyc1N0YXRlOjpBTFQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaUFjdGlvbjo6VG9nZ2xlU2VtYW50aWNTZWxlY3Rpb247CiAgICAgICAgInoiLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgVmlBY3Rpb246OkNlbnRlckFyb3VuZFZpQ3Vyc29yOwogICAgICAgICJrIiwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IFZpTW90aW9uOjpVcDsKICAgICAgICAiaiIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaU1vdGlvbjo6RG93bjsKICAgICAgICAiaCIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaU1vdGlvbjo6TGVmdDsKICAgICAgICAibCIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaU1vdGlvbjo6UmlnaHQ7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd1VwKSwgK0JpbmRpbmdNb2RlOjpWSTsgVmlNb3Rpb246OlVwOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dEb3duKSwgK0JpbmRpbmdNb2RlOjpWSTsgVmlNb3Rpb246OkRvd247CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd0xlZnQpLCArQmluZGluZ01vZGU6OlZJOyBWaU1vdGlvbjo6TGVmdDsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93UmlnaHQpLCArQmluZGluZ01vZGU6OlZJOyBWaU1vdGlvbjo6UmlnaHQ7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd1VwKSwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246Ok5vbmU7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVIsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6Tm9uZTsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93TGVmdCksIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpOb25lOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dSaWdodCksIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpOb25lOwogICAgICAgICIwIiwgICAgICAgICAgICAgICAgICAgICAgICAgICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6Rmlyc3Q7CiAgICAgICAgIjQiLCAgIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpMYXN0OwogICAgICAgICI2IiwgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6Rmlyc3RPY2N1cGllZDsKICAgICAgICAiaCIsICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsKICAgICAgICAgICAgVmlNb3Rpb246OkhpZ2g7CiAgICAgICAgIm0iLCAgICAgIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpNaWRkbGU7CiAgICAgICAgImwiLCAgICAgIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpMb3c7CiAgICAgICAgImIiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpTZW1hbnRpY0xlZnQ7CiAgICAgICAgInciLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpTZW1hbnRpY1JpZ2h0OwogICAgICAgICJlIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6U2VtYW50aWNSaWdodEVuZDsKICAgICAgICAiYiIsICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsKICAgICAgICAgICAgVmlNb3Rpb246OldvcmRMZWZ0OwogICAgICAgICJ3IiwgICAgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6V29yZFJpZ2h0OwogICAgICAgICJlIiwgICAgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6V29yZFJpZ2h0RW5kOwogICAgICAgICI1IiwgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6QnJhY2tldDsKICAgICk7CgogICAgaWYgIWNvbmZpZ19rZXlib2FyZC51c2Vfa2l0dHlfa2V5Ym9hcmRfcHJvdG9jb2wgewogICAgICAgIGJpbmRpbmdzLmV4dGVuZChiaW5kaW5ncyEoCiAgICAgICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgICAgIEtleTo6TmFtZWQoSG9tZSksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkVzYygiXHgxYlsxOzJIIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEVuZCksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkVzYygiXHgxYlsxOzJGIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEVuZCksICB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6RXNjKCJceDFiW0YiLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoUGFnZVVwKSwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYls1OzJ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VEb3duKSwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYls2OzJ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEhvbWUpLCAgfkJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbSCIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd1VwKSwgfkJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbQSIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYltCIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEFycm93UmlnaHQpLCB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYltDIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEFycm93TGVmdCksICB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYltEIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEJhY2tzcGFjZSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHg3ZiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChJbnNlcnQpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMn4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRGVsZXRlKSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzN+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VVcCksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYls1fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChQYWdlRG93biksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYls2fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYk9QIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEYyKSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiT1EiLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjMpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJPUiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGNCksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYk9TIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEY1KSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzE1fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGNiksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlsxN34iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjcpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMTh+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEY4KSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzE5fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGOSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlsyMH4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjEwKSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzIxfiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMTEpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMjN+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEYxMiksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlsyNH4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjEzKSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzI1fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMTQpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMjZ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEYxNSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlsyOH4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjE2KSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzI5fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMTcpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMzF+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEYxOCksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlszMn4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjE5KSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzMzfiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMjApLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMzR+Ii5pbnRvKCkpOwogICAgICAgICkpOwoKICAgICAgICAvLyAgIENvZGUgICAgIE1vZGlmaWVycwogICAgICAgIC8vIC0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgICAgICAvLyAgICAyICAgICB8IFNoaWZ0CiAgICAgICAgLy8gICAgMyAgICAgfCBBbHQKICAgICAgICAvLyAgICA0ICAgICB8IFNoaWZ0ICsgQWx0CiAgICAgICAgLy8gICAgNSAgICAgfCBDb250cm9sCiAgICAgICAgLy8gICAgNiAgICAgfCBTaGlmdCArIENvbnRyb2wKICAgICAgICAvLyAgICA3ICAgICB8IEFsdCArIENvbnRyb2wKICAgICAgICAvLyAgICA4ICAgICB8IFNoaWZ0ICsgQWx0ICsgQ29udHJvbAogICAgICAgIC8vIC0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgICAgICAvLwogICAgICAgIC8vIGZyb206IGh0dHBzOi8vaW52aXNpYmxlLWlzbGFuZC5uZXQveHRlcm0vY3Rsc2Vxcy9jdGxzZXFzLmh0bWwjaDItUEMtU3R5bGUtRnVuY3Rpb24tS2V5cwogICAgICAgIGxldCBtdXQgbW9kaWZpZXJzID0gdmVjIVsKICAgICAgICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULAogICAgICAgICAgICBNb2RpZmllcnNTdGF0ZTo6QUxULAogICAgICAgICAgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQgfCBNb2RpZmllcnNTdGF0ZTo6QUxULAogICAgICAgICAgICBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwKICAgICAgICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZUIHwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsCiAgICAgICAgICAgIE1vZGlmaWVyc1N0YXRlOjpBTFQgfCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwKICAgICAgICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZUIHwgTW9kaWZpZXJzU3RhdGU6OkFMVCB8IE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLAogICAgICAgIF07CgogICAgICAgIGZvciAoaW5kZXgsIG1vZHMpIGluIG1vZGlmaWVycy5kcmFpbiguLikuZW51bWVyYXRlKCkgewogICAgICAgICAgICAvLyBJZiBkaXNhYmxlX2N0bHNlcXNfYWx0IGlzIGVuYWJsZWQsIHNob3VsZCBpZ25vcmUgQUxUCiAgICAgICAgICAgIC8vIFVzZWZ1bCBmb3IgZXhhbXBsZSBpZiB3YW50IHNhbWUgYmVoYXZpb3VyIHRoYXQgVGVybWluYWwuYXBwIGhhdmUKICAgICAgICAgICAgLy8gU2luY2UgVGVybWluYWwuYXBwIGRvZXMgbm90IGRlYWwgd2l0aCBjdGxzZXFzIHdpdGggQUxUIGtleXMKICAgICAgICAgICAgaWYgaW5kZXggPT0gMSAmJiBjb25maWdfa2V5Ym9hcmQuZGlzYWJsZV9jdGxzZXFzX2FsdCB7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGV0IG1vZGlmaWVyc19jb2RlID0gaW5kZXggKyAyOwogICAgICAgICAgICBiaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRGVsZXRlKSwgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzM7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoQXJyb3dVcCksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fUEiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsxO3t9QiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEFycm93UmlnaHQpLCAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzE7e31DIiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoQXJyb3dMZWZ0KSwgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fUQiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMSksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fVAiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMiksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fVEiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMyksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fVIiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGNCksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fVMiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGNSksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTU7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjYpLCAgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzE3O3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEY3KSwgICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsxODt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGOCksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTk7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjkpLCAgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzIwO3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEYxMCksICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsyMTt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMTEpLCAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMjM7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjEyKSwgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzI0O3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEYxMyksICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsyNTt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMTQpLCAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMjY7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjE1KSwgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzI4O3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEYxNiksICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsyOTt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMTcpLCAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMzE7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjE4KSwgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzMyO3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEYxOSksICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlszMzt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMjApLCAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMzQ7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgKSk7CgogICAgICAgICAgICAvLyBXZSdyZSBhZGRpbmcgdGhlIGZvbGxvd2luZyBiaW5kaW5ncyB3aXRoIGBTaGlmdGAgbWFudWFsbHkgYWJvdmUsIHNvIHNraXBwaW5nIHRoZW0gaGVyZS4KICAgICAgICAgICAgaWYgbW9kaWZpZXJzX2NvZGUgIT0gMiB7CiAgICAgICAgICAgICAgICBiaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICAgICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgICAgICAgICAgICAgS2V5OjpOYW1lZChJbnNlcnQpLCAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMjt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoUGFnZVVwKSwgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzU7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VEb3duKSwgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYls2O3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICAgICAgS2V5OjpOYW1lZChFbmQpLCAgICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fUYiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoSG9tZSksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzE7e31IIiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgICkpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICBiaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEFycm93VXApLCB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQzsgQWN0aW9uOjpFc2MoIlx4MWJbQSIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQzsgQWN0aW9uOjpFc2MoIlx4MWJbQiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd1JpZ2h0KSwgfkJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0M7IEFjdGlvbjo6RXNjKCJceDFiW0MiLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoQXJyb3dMZWZ0KSwgIH5CaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6QUxMX0tFWVNfQVNfRVNDOyBBY3Rpb246OkVzYygiXHgxYltEIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEluc2VydCksICAgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0MsIH5CaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVM7IEFjdGlvbjo6RXNjKCJceDFiWzJ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKERlbGV0ZSksICAgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0MsIH5CaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVM7IEFjdGlvbjo6RXNjKCJceDFiWzN+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VVcCksICAgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0MsIH5CaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVM7IEFjdGlvbjo6RXNjKCJceDFiWzV+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VEb3duKSwgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0MsIH5CaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVM7IEFjdGlvbjo6RXNjKCJceDFiWzZ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEJhY2tzcGFjZSksICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0M7IEFjdGlvbjo6RXNjKCJceDdmIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEJhY2tzcGFjZSksIE1vZGlmaWVyc1N0YXRlOjpBTFQsICAgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0M7IEFjdGlvbjo6RXNjKCJceDFiXHg3ZiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChCYWNrc3BhY2UpLCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICAgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6QUxMX0tFWVNfQVNfRVNDOyBBY3Rpb246OkVzYygiXHg3ZiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQywgfkJpbmRpbmdNb2RlOjpESVNBTUJJR1VBVEVfS0VZUzsgQWN0aW9uOjpFc2MoIlx4MWJPUCIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMiksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQywgfkJpbmRpbmdNb2RlOjpESVNBTUJJR1VBVEVfS0VZUzsgQWN0aW9uOjpFc2MoIlx4MWJPUSIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMyksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQywgfkJpbmRpbmdNb2RlOjpESVNBTUJJR1VBVEVfS0VZUzsgQWN0aW9uOjpFc2MoIlx4MWJPUiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGNCksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQywgfkJpbmRpbmdNb2RlOjpESVNBTUJJR1VBVEVfS0VZUzsgQWN0aW9uOjpFc2MoIlx4MWJPUyIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChUYWIpLCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCAgIH5CaW5kaW5nTW9kZTo6QUxMX0tFWVNfQVNfRVNDOyBBY3Rpb246OkVzYygiXHgxYltaIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFRhYiksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCB8IE1vZGlmaWVyc1N0YXRlOjpBTFQsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQzsgQWN0aW9uOjpFc2MoIlx4MWJceDFiW1oiLmludG8oKSk7CiAgICAgICAgKSk7CiAgICB9CgogICAgYmluZGluZ3MuZXh0ZW5kKHBsYXRmb3JtX2tleV9iaW5kaW5ncygKICAgICAgICB1c2VfbmF2aWdhdGlvbl9rZXlfYmluZGluZ3MsCiAgICAgICAgdXNlX3NwbGl0cywKICAgICAgICBjb25maWdfa2V5Ym9hcmQsCiAgICApKTsKCiAgICBjb25maWdfa2V5X2JpbmRpbmdzKHVucHJvY2Vzc2VkX2NvbmZpZ19rZXlfYmluZGluZ3MsIGJpbmRpbmdzKQp9CgojW2Rlcml2ZShDbG9uZSwgRGVidWcsIFBhcnRpYWxFcSwgRXEpXQpwdWIgc3RydWN0IE1vZGVXcmFwcGVyIHsKICAgIHB1YiBtb2RlOiBCaW5kaW5nTW9kZSwKICAgIHB1YiBub3RfbW9kZTogQmluZGluZ01vZGUsCn0KCiNbaW5saW5lXQpmbiBjb252ZXJ0KGNvbmZpZ19rZXlfYmluZGluZzogQ29uZmlnS2V5QmluZGluZykgLT4gUmVzdWx0PEtleUJpbmRpbmcsIFN0cmluZz4gewogICAgbGV0IChrZXksIGxvY2F0aW9uKSA9IGlmIGNvbmZpZ19rZXlfYmluZGluZy5rZXkuY2hhcnMoKS5jb3VudCgpID09IDEgewogICAgICAgICgKICAgICAgICAgICAgS2V5OjpDaGFyYWN0ZXIoY29uZmlnX2tleV9iaW5kaW5nLmtleS50b19sb3dlcmNhc2UoKS5pbnRvKCkpLAogICAgICAgICAgICBLZXlMb2NhdGlvbjo6U3RhbmRhcmQsCiAgICAgICAgKQogICAgfSBlbHNlIHsKICAgICAgICBtYXRjaCBjb25maWdfa2V5X2JpbmRpbmcua2V5LnRvX2xvd2VyY2FzZSgpLmFzX3N0cigpIHsKICAgICAgICAgICAgImhvbWUiID0+IChLZXk6Ok5hbWVkKEhvbWUpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICAic3BhY2UiID0+IChLZXk6Ok5hbWVkKFNwYWNlKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgImRlbGV0ZSIgPT4gKEtleTo6TmFtZWQoRGVsZXRlKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgImVzYyIgPT4gKEtleTo6TmFtZWQoRXNjYXBlKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgImluc2VydCIgPT4gKEtleTo6TmFtZWQoSW5zZXJ0KSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgInBhZ2V1cCIgPT4gKEtleTo6TmFtZWQoUGFnZVVwKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgInBhZ2Vkb3duIiA9PiAoS2V5OjpOYW1lZChQYWdlRG93biksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJlbmQiID0+IChLZXk6Ok5hbWVkKEVuZCksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJ1cCIgPT4gKEtleTo6TmFtZWQoQXJyb3dVcCksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJiYWNrIiA9PiAoS2V5OjpOYW1lZChCYWNrc3BhY2UpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICAiZG93biIgPT4gKEtleTo6TmFtZWQoQXJyb3dEb3duKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgImxlZnQiID0+IChLZXk6Ok5hbWVkKEFycm93TGVmdCksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJyaWdodCIgPT4gKEtleTo6TmFtZWQoQXJyb3dSaWdodCksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJAIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIkAiLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJjb2xvbiIgPT4gKEtleTo6Q2hhcmFjdGVyKCI6Ii5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICAiLiIgPT4gKEtleTo6Q2hhcmFjdGVyKCIuIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICAicmV0dXJuIiA9PiAoS2V5OjpOYW1lZChFbnRlciksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJbIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIlsiLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJdIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIl0iLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJ7IiA9PiAoS2V5OjpDaGFyYWN0ZXIoInsiLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJ9IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIn0iLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICI7IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjsiLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJcXCIgPT4gKEtleTo6Q2hhcmFjdGVyKCJcXCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIisiID0+IChLZXk6OkNoYXJhY3RlcigiKyIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIiwiID0+IChLZXk6OkNoYXJhY3RlcigiLCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIi8iID0+IChLZXk6OkNoYXJhY3RlcigiLyIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIj0iID0+IChLZXk6OkNoYXJhY3RlcigiPSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIi0iID0+IChLZXk6OkNoYXJhY3RlcigiLSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIioiID0+IChLZXk6OkNoYXJhY3RlcigiKiIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjEiID0+IChLZXk6OkNoYXJhY3RlcigiMSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjIiID0+IChLZXk6OkNoYXJhY3RlcigiMiIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjMiID0+IChLZXk6OkNoYXJhY3RlcigiMyIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjQiID0+IChLZXk6OkNoYXJhY3RlcigiNCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjUiID0+IChLZXk6OkNoYXJhY3RlcigiNSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjYiID0+IChLZXk6OkNoYXJhY3RlcigiNiIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjciID0+IChLZXk6OkNoYXJhY3RlcigiNyIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjgiID0+IChLZXk6OkNoYXJhY3RlcigiOCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjkiID0+IChLZXk6OkNoYXJhY3RlcigiOSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjAiID0+IChLZXk6OkNoYXJhY3RlcigiMCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKCiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBudW1wYWQuCiAgICAgICAgICAgICJudW1wYWRlbnRlciIgPT4gKEtleTo6TmFtZWQoRW50ZXIpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZGFkZCIgPT4gKEtleTo6Q2hhcmFjdGVyKCIrIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZGNvbW1hIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIiwiLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkZGVjaW1hbCIgPT4gKEtleTo6Q2hhcmFjdGVyKCIuIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZGRpdmlkZSIgPT4gKEtleTo6Q2hhcmFjdGVyKCIvIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZGVxdWFscyIgPT4gKEtleTo6Q2hhcmFjdGVyKCI9Ii5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZHN1YnRyYWN0IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIi0iLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkbXVsdGlwbHkiID0+IChLZXk6OkNoYXJhY3RlcigiKiIuaW50bygpKSwgS2V5TG9jYXRpb246Ok51bXBhZCksCiAgICAgICAgICAgICJudW1wYWQxIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjEiLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkMiIgPT4gKEtleTo6Q2hhcmFjdGVyKCIyIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZDMiID0+IChLZXk6OkNoYXJhY3RlcigiMyIuaW50bygpKSwgS2V5TG9jYXRpb246Ok51bXBhZCksCiAgICAgICAgICAgICJudW1wYWQ0IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjQiLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkNSIgPT4gKEtleTo6Q2hhcmFjdGVyKCI1Ii5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZDYiID0+IChLZXk6OkNoYXJhY3RlcigiNiIuaW50bygpKSwgS2V5TG9jYXRpb246Ok51bXBhZCksCiAgICAgICAgICAgICJudW1wYWQ3IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjciLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkOCIgPT4gKEtleTo6Q2hhcmFjdGVyKCI4Ii5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZDkiID0+IChLZXk6OkNoYXJhY3RlcigiOSIuaW50bygpKSwgS2V5TG9jYXRpb246Ok51bXBhZCksCiAgICAgICAgICAgICJudW1wYWQwIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjAiLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAoKICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlcwogICAgICAgICAgICAidGFiIiA9PiAoS2V5OjpOYW1lZChUYWIpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICBfID0+IHJldHVybiBFcnIoIlVuYWJsZSB0byBmaW5kIGRlZmluZWQgJ2tleWNvZGUnIi50b19zdHJpbmcoKSksCiAgICAgICAgfQogICAgfTsKCiAgICBsZXQgdHJpZ2dlciA9IEJpbmRpbmdLZXk6OktleWNvZGUgeyBrZXksIGxvY2F0aW9uIH07CgogICAgbGV0IG11dCByZXMgPSBNb2RpZmllcnNTdGF0ZTo6ZW1wdHkoKTsKICAgIGZvciBtb2RpZmllciBpbiBjb25maWdfa2V5X2JpbmRpbmcud2l0aC5zcGxpdCgnfCcpIHsKICAgICAgICBtYXRjaCBtb2RpZmllci50cmltKCkudG9fbG93ZXJjYXNlKCkuYXNfc3RyKCkgewogICAgICAgICAgICAiY29tbWFuZCIgfCAic3VwZXIiID0+IHJlcy5pbnNlcnQoTW9kaWZpZXJzU3RhdGU6OlNVUEVSKSwKICAgICAgICAgICAgInNoaWZ0IiA9PiByZXMuaW5zZXJ0KE1vZGlmaWVyc1N0YXRlOjpTSElGVCksCiAgICAgICAgICAgICJhbHQiIHwgIm9wdGlvbiIgPT4gcmVzLmluc2VydChNb2RpZmllcnNTdGF0ZTo6QUxUKSwKICAgICAgICAgICAgImNvbnRyb2wiID0+IHJlcy5pbnNlcnQoTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wpLAogICAgICAgICAgICAibm9uZSIgPT4gKCksCiAgICAgICAgICAgIF8gPT4gKCksCiAgICAgICAgfQogICAgfQoKICAgIGxldCBtdXQgYWN0aW9uOiBBY3Rpb24gPSBjb25maWdfa2V5X2JpbmRpbmcuYWN0aW9uLmludG8oKTsKICAgIGlmICFjb25maWdfa2V5X2JpbmRpbmcudGV4dC5pc19lbXB0eSgpIHsKICAgICAgICBhY3Rpb24gPSBBY3Rpb246OkVzYyhjb25maWdfa2V5X2JpbmRpbmcudGV4dCk7CiAgICB9CgogICAgaWYgIWNvbmZpZ19rZXlfYmluZGluZy5ieXRlcy5pc19lbXB0eSgpIHsKICAgICAgICBpZiBsZXQgT2soc3RyX2Zyb21fYnl0ZXMpID0gc3RkOjpzdHI6OmZyb21fdXRmOCgmY29uZmlnX2tleV9iaW5kaW5nLmJ5dGVzKSB7CiAgICAgICAgICAgIGFjdGlvbiA9IEFjdGlvbjo6RXNjKHN0cl9mcm9tX2J5dGVzLmludG8oKSk7CiAgICAgICAgfQogICAgfQoKICAgIGxldCBtdXQgcmVzX21vZGUgPSBNb2RlV3JhcHBlciB7CiAgICAgICAgbW9kZTogQmluZGluZ01vZGU6OmVtcHR5KCksCiAgICAgICAgbm90X21vZGU6IEJpbmRpbmdNb2RlOjplbXB0eSgpLAogICAgfTsKCiAgICBmb3IgbW9kaWZpZXIgaW4gY29uZmlnX2tleV9iaW5kaW5nLm1vZGUuc3BsaXQoJ3wnKSB7CiAgICAgICAgbWF0Y2ggbW9kaWZpZXIudHJpbSgpLnRvX2xvd2VyY2FzZSgpLmFzX3N0cigpIHsKICAgICAgICAgICAgImFwcGN1cnNvciIgPT4gcmVzX21vZGUubW9kZSB8PSBCaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwKICAgICAgICAgICAgIn5hcHBjdXJzb3IiID0+IHJlc19tb2RlLm5vdF9tb2RlIHw9IEJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLAogICAgICAgICAgICAiYXBwa2V5cGFkIiA9PiByZXNfbW9kZS5tb2RlIHw9IEJpbmRpbmdNb2RlOjpBUFBfS0VZUEFELAogICAgICAgICAgICAifmFwcGtleXBhZCIgPT4gcmVzX21vZGUubm90X21vZGUgfD0gQmluZGluZ01vZGU6OkFQUF9LRVlQQUQsCiAgICAgICAgICAgICJhbHQiID0+IHJlc19tb2RlLm1vZGUgfD0gQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sCiAgICAgICAgICAgICJ+YWx0IiA9PiByZXNfbW9kZS5ub3RfbW9kZSB8PSBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgInZpIiA9PiByZXNfbW9kZS5tb2RlIHw9IEJpbmRpbmdNb2RlOjpWSSwKICAgICAgICAgICAgIn52aSIgPT4gcmVzX21vZGUubm90X21vZGUgfD0gQmluZGluZ01vZGU6OlZJLAogICAgICAgICAgICBfID0+IHsKICAgICAgICAgICAgICAgIHJlc19tb2RlLm5vdF9tb2RlIHw9IEJpbmRpbmdNb2RlOjplbXB0eSgpOwogICAgICAgICAgICAgICAgcmVzX21vZGUubW9kZSB8PSBCaW5kaW5nTW9kZTo6ZW1wdHkoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBPayhLZXlCaW5kaW5nIHsKICAgICAgICB0cmlnZ2VyLAogICAgICAgIG1vZHM6IHJlcywKICAgICAgICBhY3Rpb24sCiAgICAgICAgbW9kZTogcmVzX21vZGUubW9kZSwKICAgICAgICBub3Rtb2RlOiByZXNfbW9kZS5ub3RfbW9kZSwKICAgIH0pCn0KCnB1YiBmbiBjb25maWdfa2V5X2JpbmRpbmdzKAogICAgY29uZmlnX2tleV9iaW5kaW5nczogVmVjPENvbmZpZ0tleUJpbmRpbmc+LAogICAgbXV0IGJpbmRpbmdzOiBWZWM8S2V5QmluZGluZz4sCikgLT4gVmVjPEtleUJpbmRpbmc+IHsKICAgIGlmIGNvbmZpZ19rZXlfYmluZGluZ3MuaXNfZW1wdHkoKSB7CiAgICAgICAgcmV0dXJuIGJpbmRpbmdzOwogICAgfQoKICAgIGZvciBja2IgaW4gY29uZmlnX2tleV9iaW5kaW5ncyB7CiAgICAgICAgbWF0Y2ggY29udmVydChja2IpIHsKICAgICAgICAgICAgT2soa2V5X2JpbmRpbmcpID0+IG1hdGNoIGtleV9iaW5kaW5nLmFjdGlvbiB7CiAgICAgICAgICAgICAgICBBY3Rpb246Ok5vbmUgfCBBY3Rpb246OlJlY2VpdmVDaGFyID0+IHsKICAgICAgICAgICAgICAgICAgICBsZXQgbXV0IGZvdW5kX2lkeCA9IE5vbmU7CiAgICAgICAgICAgICAgICAgICAgZm9yIChpZHgsIGJpbmRpbmcpIGluIGJpbmRpbmdzLml0ZXIoKS5lbnVtZXJhdGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIGJpbmRpbmcudHJpZ2dlcnNfbWF0Y2goJmtleV9iaW5kaW5nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3VuZF9pZHggPSBTb21lKGlkeCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgaWYgbGV0IFNvbWUoaWR4KSA9IGZvdW5kX2lkeCB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJpbmRpbmdzLnJlbW92ZShpZHgpOwogICAgICAgICAgICAgICAgICAgICAgICB0cmFjaW5nOjp3YXJuISgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvdmVyd3JpdHRlbiBhIHByZXZpb3VzIGtleV9iaW5kaW5nIHdpdGggbmV3IG9uZTogezo/fSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlfYmluZGluZwogICAgICAgICAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNpbmc6OmluZm8hKCJhZGRlZCBhIG5ldyBrZXlfYmluZGluZzogezo/fSIsIGtleV9iaW5kaW5nKTsKICAgICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgICAgIGJpbmRpbmdzLnB1c2goa2V5X2JpbmRpbmcpCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBfID0+IHsKICAgICAgICAgICAgICAgICAgICB0cmFjaW5nOjppbmZvISgiYWRkZWQgYSBuZXcga2V5X2JpbmRpbmc6IHs6P30iLCBrZXlfYmluZGluZyk7CiAgICAgICAgICAgICAgICAgICAgYmluZGluZ3MucHVzaChrZXlfYmluZGluZykKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgRXJyKGVycl9tZXNzYWdlKSA9PiB7CiAgICAgICAgICAgICAgICB0cmFjaW5nOjplcnJvciEoImVycm9yIGxvYWRpbmcgYSBrZXkgYmluZGluZzogezo/fSIsIGVycl9tZXNzYWdlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBiaW5kaW5ncwp9CgovLyBNYWNvcwojW2NmZyhhbGwodGFyZ2V0X29zID0gIm1hY29zIiwgbm90KHRlc3QpKSldCnB1YiBmbiBwbGF0Zm9ybV9rZXlfYmluZGluZ3MoCiAgICB1c2VfbmF2aWdhdGlvbl9rZXlfYmluZGluZ3M6IGJvb2wsCiAgICB1c2Vfc3BsaXRzOiBib29sLAogICAgY29uZmlnX2tleWJvYXJkOiBDb25maWdLZXlib2FyZCwKKSAtPiBWZWM8S2V5QmluZGluZz4gewogICAgbGV0IG11dCBrZXlfYmluZGluZ3MgPSBiaW5kaW5ncyEoCiAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAiMCIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpSZXNldEZvbnRTaXplOwogICAgICAgICI9IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OkluY3JlYXNlRm9udFNpemU7CiAgICAgICAgIisiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6SW5jcmVhc2VGb250U2l6ZTsKICAgICAgICAiKyIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpJbmNyZWFzZUZvbnRTaXplOwogICAgICAgICItIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OkRlY3JlYXNlRm9udFNpemU7CiAgICAgICAgIi0iLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6RGVjcmVhc2VGb250U2l6ZTsKICAgICAgICBLZXk6Ok5hbWVkKEluc2VydCksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIEFjdGlvbjo6RXNjKCJceDFiWzI7Mn4iLmludG8oKSk7CiAgICAgICAgImsiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVIsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBBY3Rpb246OkVzYygiXHgwYyIuaW50bygpKTsKICAgICAgICAiayIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpWSTsgIEFjdGlvbjo6Q2xlYXJIaXN0b3J5OwogICAgICAgICJ2IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlBhc3RlOwogICAgICAgICJmIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6VG9nZ2xlRnVsbHNjcmVlbjsKICAgICAgICAiYyIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpDb3B5OwogICAgICAgICJjIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCArQmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkNsZWFyU2VsZWN0aW9uOwogICAgICAgICJoIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OkhpZGU7CiAgICAgICAgImgiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVIgfCBNb2RpZmllcnNTdGF0ZTo6QUxUOyBBY3Rpb246OkhpZGVPdGhlckFwcGxpY2F0aW9uczsKICAgICAgICAibSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpNaW5pbWl6ZTsKICAgICAgICAicSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpRdWl0OwogICAgICAgICJuIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OldpbmRvd0NyZWF0ZU5ldzsKICAgICAgICAiLCIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpDb25maWdFZGl0b3I7CgogICAgICAgIC8vIFNlYXJjaAogICAgICAgICJmIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTZWFyY2hGb3J3YXJkOwogICAgICAgICJiIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTZWFyY2hCYWNrd2FyZDsKICAgICAgICAiYyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hDYW5jZWw7CiAgICAgICAgInUiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoQ2xlYXI7CiAgICAgICAgInciLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgICtCaW5kaW5nTW9kZTo6U0VBUkNIOyBTZWFyY2hBY3Rpb246OlNlYXJjaERlbGV0ZVdvcmQ7CiAgICAgICAgInAiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgICtCaW5kaW5nTW9kZTo6U0VBUkNIOyBTZWFyY2hBY3Rpb246OlNlYXJjaEhpc3RvcnlQcmV2aW91czsKICAgICAgICAibiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeU5leHQ7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd1VwKSwgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeVByZXZpb3VzOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dEb3duKSwgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeU5leHQ7CiAgICApOwoKICAgIGlmIHVzZV9uYXZpZ2F0aW9uX2tleV9iaW5kaW5ncyB7CiAgICAgICAga2V5X2JpbmRpbmdzLmV4dGVuZChiaW5kaW5ncyEoCiAgICAgICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgICAgICJ0IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OlRhYkNyZWF0ZU5ldzsKICAgICAgICAgICAgS2V5OjpOYW1lZChUYWIpLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgQWN0aW9uOjpTZWxlY3ROZXh0VGFiOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFRhYiksIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlNlbGVjdFByZXZUYWI7CiAgICAgICAgICAgICJ3IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OkNsb3NlQ3VycmVudFNwbGl0T3JUYWI7CiAgICAgICAgICAgICJbIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlNlbGVjdFByZXZUYWI7CiAgICAgICAgICAgICJdIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlNlbGVjdE5leHRUYWI7CiAgICAgICAgICAgICIxIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OlNlbGVjdFRhYigwKTsKICAgICAgICAgICAgIjIiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6U2VsZWN0VGFiKDEpOwogICAgICAgICAgICAiMyIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpTZWxlY3RUYWIoMik7CiAgICAgICAgICAgICI0IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OlNlbGVjdFRhYigzKTsKICAgICAgICAgICAgIjUiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6U2VsZWN0VGFiKDQpOwogICAgICAgICAgICAiNiIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpTZWxlY3RUYWIoNSk7CiAgICAgICAgICAgICI3IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OlNlbGVjdFRhYig2KTsKICAgICAgICAgICAgIjgiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6U2VsZWN0VGFiKDcpOwogICAgICAgICAgICAiOSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpTZWxlY3RMYXN0VGFiOwogICAgICAgICkpOwogICAgfQoKICAgIGlmIGNvbmZpZ19rZXlib2FyZC5kaXNhYmxlX2N0bHNlcXNfYWx0IHsKICAgICAgICBrZXlfYmluZGluZ3MuZXh0ZW5kKGJpbmRpbmdzISgKICAgICAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd0xlZnQpLCBNb2RpZmllcnNTdGF0ZTo6QUxULCAgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKCJceDFiYiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd1JpZ2h0KSwgTW9kaWZpZXJzU3RhdGU6OkFMVCwgIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICBBY3Rpb246OkVzYygiXHgxYmYiLmludG8oKSk7CiAgICAgICAgKSk7CiAgICB9CgogICAgaWYgdXNlX3NwbGl0cyB7CiAgICAgICAga2V5X2JpbmRpbmdzLmV4dGVuZChiaW5kaW5ncyEoCiAgICAgICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgICAgICJkIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdFJpZ2h0OwogICAgICAgICAgICAiZCIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U3BsaXREb3duOwogICAgICAgICAgICAiXSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U2VsZWN0TmV4dFNwbGl0OwogICAgICAgICAgICAiWyIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U2VsZWN0UHJldlNwbGl0OwogICAgICAgICkpOwogICAgfQoKICAgIGtleV9iaW5kaW5ncwp9CgovLyBOb3QgV2luZG93cywgTWFjb3MKI1tjZmcobm90KGFueSh0YXJnZXRfb3MgPSAibWFjb3MiLCB0YXJnZXRfb3MgPSAid2luZG93cyIsIHRlc3QpKSldCnB1YiBmbiBwbGF0Zm9ybV9rZXlfYmluZGluZ3MoCiAgICB1c2VfbmF2aWdhdGlvbl9rZXlfYmluZGluZ3M6IGJvb2wsCiAgICB1c2Vfc3BsaXRzOiBib29sLAogICAgXzogQ29uZmlnS2V5Ym9hcmQsCikgLT4gVmVjPEtleUJpbmRpbmc+IHsKICAgIGxldCBtdXQga2V5X2JpbmRpbmdzID0gYmluZGluZ3MhKAogICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgInYiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpQYXN0ZTsKICAgICAgICAiYyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OkNvcHk7CiAgICAgICAgImMiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwKICAgICAgICAgICAgK0JpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpDbGVhclNlbGVjdGlvbjsKICAgICAgICBLZXk6Ok5hbWVkKEluc2VydCksICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlBhc3RlU2VsZWN0aW9uOwogICAgICAgICIwIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7ICBBY3Rpb246OlJlc2V0Rm9udFNpemU7CiAgICAgICAgIj0iLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgIEFjdGlvbjo6SW5jcmVhc2VGb250U2l6ZTsKICAgICAgICAiKyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyAgQWN0aW9uOjpJbmNyZWFzZUZvbnRTaXplOwogICAgICAgICIrIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7ICBBY3Rpb246OkluY3JlYXNlRm9udFNpemU7CiAgICAgICAgIi0iLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgIEFjdGlvbjo6RGVjcmVhc2VGb250U2l6ZTsKICAgICAgICAiLSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyAgQWN0aW9uOjpEZWNyZWFzZUZvbnRTaXplOwogICAgICAgICJuIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6V2luZG93Q3JlYXRlTmV3OwogICAgICAgICIsIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6Q29uZmlnRWRpdG9yOwoKICAgICAgICAvLyBTZWFyY2gKICAgICAgICAiZiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTZWFyY2hGb3J3YXJkOwogICAgICAgICJiIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNlYXJjaEJhY2t3YXJkOwogICAgICAgICJjIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsICtCaW5kaW5nTW9kZTo6U0VBUkNIOyBTZWFyY2hBY3Rpb246OlNlYXJjaENhbmNlbDsKICAgICAgICAidSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hDbGVhcjsKICAgICAgICAidyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoRGVsZXRlV29yZDsKICAgICAgICAicCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeVByZXZpb3VzOwogICAgICAgICJuIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsICArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dDsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93VXApLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5UHJldmlvdXM7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dDsKICAgICk7CgogICAgaWYgdXNlX25hdmlnYXRpb25fa2V5X2JpbmRpbmdzIHsKICAgICAgICBrZXlfYmluZGluZ3MuZXh0ZW5kKGJpbmRpbmdzISgKICAgICAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAgICAgInQiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpUYWJDcmVhdGVOZXc7CiAgICAgICAgICAgIEtleTo6TmFtZWQoVGFiKSwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7IEFjdGlvbjo6U2VsZWN0TmV4dFRhYjsKICAgICAgICAgICAgS2V5OjpOYW1lZChUYWIpLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpTZWxlY3RQcmV2VGFiOwogICAgICAgICAgICAiWyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlNlbGVjdFByZXZUYWI7CiAgICAgICAgICAgICJdIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6U2VsZWN0TmV4dFRhYjsKICAgICAgICAgICAgInciLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpDbG9zZUN1cnJlbnRTcGxpdE9yVGFiOwogICAgICAgICkpOwogICAgfQoKICAgIGlmIHVzZV9zcGxpdHMgewogICAgICAgIGtleV9iaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICAgICAiciIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdFJpZ2h0OwogICAgICAgICAgICAiZCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdERvd247CiAgICAgICAgICAgICJdIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlNlbGVjdE5leHRTcGxpdDsKICAgICAgICAgICAgIlsiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U2VsZWN0UHJldlNwbGl0OwogICAgICAgICkpOwogICAgfQoKICAgIGtleV9iaW5kaW5ncwp9CgovLyBXaW5kb3dzCiNbY2ZnKGFsbCh0YXJnZXRfb3MgPSAid2luZG93cyIsIG5vdCh0ZXN0KSkpXQpwdWIgZm4gcGxhdGZvcm1fa2V5X2JpbmRpbmdzKAogICAgdXNlX25hdmlnYXRpb25fa2V5X2JpbmRpbmdzOiBib29sLAogICAgdXNlX3NwbGl0czogYm9vbCwKICAgIF86IENvbmZpZ0tleWJvYXJkLAopIC0+IFZlYzxLZXlCaW5kaW5nPiB7CiAgICBsZXQgbXV0IGtleV9iaW5kaW5ncyA9IGJpbmRpbmdzISgKICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICJ2IiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6UGFzdGU7CiAgICAgICAgImMiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpDb3B5OwogICAgICAgICJjIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6Q2xlYXJTZWxlY3Rpb247CiAgICAgICAgS2V5OjpOYW1lZChJbnNlcnQpLCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6UGFzdGVTZWxlY3Rpb247CiAgICAgICAgIjAiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgQWN0aW9uOjpSZXNldEZvbnRTaXplOwogICAgICAgICI9IiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7IEFjdGlvbjo6SW5jcmVhc2VGb250U2l6ZTsKICAgICAgICAiKyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyBBY3Rpb246OkluY3JlYXNlRm9udFNpemU7CiAgICAgICAgIisiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgQWN0aW9uOjpJbmNyZWFzZUZvbnRTaXplOwogICAgICAgICItIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7IEFjdGlvbjo6RGVjcmVhc2VGb250U2l6ZTsKICAgICAgICAiLSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyBBY3Rpb246OkRlY3JlYXNlRm9udFNpemU7CiAgICAgICAgS2V5OjpOYW1lZChFbnRlciksIE1vZGlmaWVyc1N0YXRlOjpBTFQ7IEFjdGlvbjo6VG9nZ2xlRnVsbHNjcmVlbjsKICAgICAgICAibiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OldpbmRvd0NyZWF0ZU5ldzsKICAgICAgICAiLCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OkNvbmZpZ0VkaXRvcjsKICAgICAgICAvLyBUaGlzIGlzIGFjdHVhbGx5IGEgV2luZG93cyBQb3dlcnNoZWxsIHNob3J0Y3V0CiAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2FsYWNyaXR0eS9hbGFjcml0dHkvaXNzdWVzLzI5MzAKICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vcmFwaGFtb3JpbS9yaW8vaXNzdWVzLzIyMCNpc3N1ZWNvbW1lbnQtMTc2MTY1MTMzOQogICAgICAgIEtleTo6TmFtZWQoQmFja3NwYWNlKSwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6RXNjKCJcdXswMDE3fSIuaW50bygpKTsKICAgICAgICBLZXk6Ok5hbWVkKFNwYWNlKSwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6VG9nZ2xlVmlNb2RlOwoKICAgICAgICAvLyBTZWFyY2gKICAgICAgICAiZiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTZWFyY2hGb3J3YXJkOwogICAgICAgICJiIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNlYXJjaEJhY2t3YXJkOwogICAgICAgICJjIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsICtCaW5kaW5nTW9kZTo6U0VBUkNIOyBTZWFyY2hBY3Rpb246OlNlYXJjaENhbmNlbDsKICAgICAgICAidSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hDbGVhcjsKICAgICAgICAidyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoRGVsZXRlV29yZDsKICAgICAgICAicCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeVByZXZpb3VzOwogICAgICAgICJuIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsICArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dDsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93VXApLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5UHJldmlvdXM7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dDsKICAgICk7CgogICAgaWYgdXNlX25hdmlnYXRpb25fa2V5X2JpbmRpbmdzIHsKICAgICAgICBrZXlfYmluZGluZ3MuZXh0ZW5kKGJpbmRpbmdzISgKICAgICAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAgICAgInQiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpUYWJDcmVhdGVOZXc7CiAgICAgICAgICAgIEtleTo6TmFtZWQoVGFiKSwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7IEFjdGlvbjo6U2VsZWN0TmV4dFRhYjsKICAgICAgICAgICAgS2V5OjpOYW1lZChUYWIpLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpTZWxlY3RQcmV2VGFiOwogICAgICAgICAgICAidyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OkNsb3NlQ3VycmVudFNwbGl0T3JUYWI7CiAgICAgICAgICAgICJbIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6U2VsZWN0UHJldlRhYjsKICAgICAgICAgICAgIl0iLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpTZWxlY3ROZXh0VGFiOwogICAgICAgICkpOwogICAgfQoKICAgIGlmIHVzZV9zcGxpdHMgewogICAgICAgIGtleV9iaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICAgICAiciIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdFJpZ2h0OwogICAgICAgICAgICAiZCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdERvd247CiAgICAgICAgICAgICJdIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlNlbGVjdE5leHRTcGxpdDsKICAgICAgICAgICAgIlsiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U2VsZWN0UHJldlNwbGl0OwogICAgICAgICkpOwogICAgfQoKICAgIGtleV9iaW5kaW5ncwp9CgojW2NmZyh0ZXN0KV0KcHViIGZuIHBsYXRmb3JtX2tleV9iaW5kaW5ncyhfOiBib29sLCBfOiBib29sLCBfOiBDb25maWdLZXlib2FyZCkgLT4gVmVjPEtleUJpbmRpbmc+IHsKICAgIHZlYyFbXQp9CgojW2NmZyh0ZXN0KV0KbW9kIHRlc3RzIHsKICAgIHVzZSBzdXBlcjo6KjsKCiAgICB1c2UgcmlvX3dpbmRvdzo6a2V5Ym9hcmQ6Ok1vZGlmaWVyc1N0YXRlOwoKICAgIHR5cGUgTW9ja0JpbmRpbmcgPSBCaW5kaW5nPHVzaXplPjsKCiAgICBpbXBsIERlZmF1bHQgZm9yIE1vY2tCaW5kaW5nIHsKICAgICAgICBmbiBkZWZhdWx0KCkgLT4gU2VsZiB7CiAgICAgICAgICAgIFNlbGYgewogICAgICAgICAgICAgICAgbW9kczogRGVmYXVsdDo6ZGVmYXVsdCgpLAogICAgICAgICAgICAgICAgYWN0aW9uOiBBY3Rpb246Ok5vbmUsCiAgICAgICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6ZW1wdHkoKSwKICAgICAgICAgICAgICAgIG5vdG1vZGU6IEJpbmRpbmdNb2RlOjplbXB0eSgpLAogICAgICAgICAgICAgICAgdHJpZ2dlcjogRGVmYXVsdDo6ZGVmYXVsdCgpLAogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfbWF0Y2hlc19pdHNlbGYoKSB7CiAgICAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZzo6ZGVmYXVsdCgpOwogICAgICAgIGxldCBpZGVudGljYWxfYmluZGluZyA9IE1vY2tCaW5kaW5nOjpkZWZhdWx0KCk7CgogICAgICAgIGFzc2VydCEoYmluZGluZy50cmlnZ2Vyc19tYXRjaCgmaWRlbnRpY2FsX2JpbmRpbmcpKTsKICAgICAgICBhc3NlcnQhKGlkZW50aWNhbF9iaW5kaW5nLnRyaWdnZXJzX21hdGNoKCZiaW5kaW5nKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ19tYXRjaGVzX2RpZmZlcmVudF9hY3Rpb24oKSB7CiAgICAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZzo6ZGVmYXVsdCgpOwogICAgICAgIGxldCBkaWZmZXJlbnRfYWN0aW9uID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBhY3Rpb246IEFjdGlvbjo6Q2xlYXJIaXN0b3J5LAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBhc3NlcnQhKGJpbmRpbmcudHJpZ2dlcnNfbWF0Y2goJmRpZmZlcmVudF9hY3Rpb24pKTsKICAgICAgICBhc3NlcnQhKGRpZmZlcmVudF9hY3Rpb24udHJpZ2dlcnNfbWF0Y2goJmJpbmRpbmcpKTsKICAgIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBtb2RzX2JpbmRpbmdfcmVxdWlyZXNfc3RyaWN0X21hdGNoKCkgewogICAgICAgIGxldCBzdXBlcnNldF9tb2RzID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RzOiBNb2RpZmllcnNTdGF0ZTo6YWxsKCksCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IHN1YnNldF9tb2RzID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RzOiBNb2RpZmllcnNTdGF0ZTo6QUxULAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBhc3NlcnQhKCFzdXBlcnNldF9tb2RzLnRyaWdnZXJzX21hdGNoKCZzdWJzZXRfbW9kcykpOwogICAgICAgIGFzc2VydCEoIXN1YnNldF9tb2RzLnRyaWdnZXJzX21hdGNoKCZzdXBlcnNldF9tb2RzKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ19tYXRjaGVzX2lkZW50aWNhbF9tb2RlKCkgewogICAgICAgIGxldCBiMSA9IE1vY2tCaW5kaW5nIHsKICAgICAgICAgICAgbW9kZTogQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgYXNzZXJ0IShiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgICAgICBhc3NlcnQhKGIyLnRyaWdnZXJzX21hdGNoKCZiMSkpOwogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfd2l0aG91dF9tb2RlX21hdGNoZXNfYW55X21vZGUoKSB7CiAgICAgICAgbGV0IGIxID0gTW9ja0JpbmRpbmc6OmRlZmF1bHQoKTsKICAgICAgICBsZXQgYjIgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG1vZGU6IEJpbmRpbmdNb2RlOjpBUFBfS0VZUEFELAogICAgICAgICAgICBub3Rtb2RlOiBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgYXNzZXJ0IShiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBiaW5kaW5nX3dpdGhfbW9kZV9tYXRjaGVzX2VtcHR5X21vZGUoKSB7CiAgICAgICAgbGV0IGIxID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QVBQX0tFWVBBRCwKICAgICAgICAgICAgbm90bW9kZTogQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmc6OmRlZmF1bHQoKTsKCiAgICAgICAgYXNzZXJ0IShiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgICAgICBhc3NlcnQhKGIyLnRyaWdnZXJzX21hdGNoKCZiMSkpOwogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfbWF0Y2hlc19tb2RlcygpIHsKICAgICAgICBsZXQgYjEgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG1vZGU6IEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOIHwgQmluZGluZ01vZGU6OkFQUF9LRVlQQUQsCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QVBQX0tFWVBBRCwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgYXNzZXJ0IShiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgICAgICBhc3NlcnQhKGIyLnRyaWdnZXJzX21hdGNoKCZiMSkpOwogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfbWF0Y2hlc19wYXJ0aWFsX2ludGVyc2VjdGlvbigpIHsKICAgICAgICBsZXQgYjEgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG1vZGU6IEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOIHwgQmluZGluZ01vZGU6OkFQUF9LRVlQQUQsCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QVBQX0tFWVBBRCB8IEJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBhc3NlcnQhKGIxLnRyaWdnZXJzX21hdGNoKCZiMikpOwogICAgICAgIGFzc2VydCEoYjIudHJpZ2dlcnNfbWF0Y2goJmIxKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ19taXNtYXRjaGVzX25vdG1vZGUoKSB7CiAgICAgICAgbGV0IGIxID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKICAgICAgICBsZXQgYjIgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG5vdG1vZGU6IEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBhc3NlcnQhKCFiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgICAgICBhc3NlcnQhKCFiMi50cmlnZ2Vyc19tYXRjaCgmYjEpKTsKICAgIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBiaW5kaW5nX21pc21hdGNoZXNfdW5yZWxhdGVkKCkgewogICAgICAgIGxldCBiMSA9IE1vY2tCaW5kaW5nIHsKICAgICAgICAgICAgbW9kZTogQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QVBQX0tFWVBBRCwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgYXNzZXJ0ISghYjEudHJpZ2dlcnNfbWF0Y2goJmIyKSk7CiAgICAgICAgYXNzZXJ0ISghYjIudHJpZ2dlcnNfbWF0Y2goJmIxKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ19tYXRjaGVzX25vdG1vZGVzKCkgewogICAgICAgIGxldCBzdWJzZXRfbm90bW9kZXMgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG5vdG1vZGU6IEJpbmRpbmdNb2RlOjpWSSB8IEJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwogICAgICAgIGxldCBzdXBlcnNldF9ub3Rtb2RlcyA9IE1vY2tCaW5kaW5nIHsKICAgICAgICAgICAgbm90bW9kZTogQmluZGluZ01vZGU6OkFQUF9DVVJTT1IsCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CgogICAgICAgIGFzc2VydCEoc3Vic2V0X25vdG1vZGVzLnRyaWdnZXJzX21hdGNoKCZzdXBlcnNldF9ub3Rtb2RlcykpOwogICAgICAgIGFzc2VydCEoc3VwZXJzZXRfbm90bW9kZXMudHJpZ2dlcnNfbWF0Y2goJnN1YnNldF9ub3Rtb2RlcykpOwogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfbWF0Y2hlc19tb2RlX25vdG1vZGUoKSB7CiAgICAgICAgbGV0IGIxID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6VkksCiAgICAgICAgICAgIG5vdG1vZGU6IEJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwogICAgICAgIGxldCBiMiA9IE1vY2tCaW5kaW5nIHsKICAgICAgICAgICAgbm90bW9kZTogQmluZGluZ01vZGU6OkFQUF9DVVJTT1IsCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CgogICAgICAgIGFzc2VydCEoYjEudHJpZ2dlcnNfbWF0Y2goJmIyKSk7CiAgICAgICAgYXNzZXJ0IShiMi50cmlnZ2Vyc19tYXRjaCgmYjEpKTsKICAgIH0KCiAgICAvLyAjW3Rlc3RdCiAgICAvLyBmbiBiaW5kaW5nX3RyaWdnZXJfaW5wdXQoKSB7CiAgICAvLyAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZyB7IHRyaWdnZXI6IDEzLCAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkgfTsKCiAgICAvLyAgICAgbGV0IG1vZHMgPSBiaW5kaW5nLm1vZHM7CiAgICAvLyAgICAgbGV0IG1vZGUgPSBiaW5kaW5nLm1vZGU7CgogICAgLy8gICAgIGFzc2VydCEoYmluZGluZy5pc190cmlnZ2VyZWRfYnkobW9kZSwgbW9kcywgJjEzKSk7CiAgICAvLyAgICAgYXNzZXJ0ISghYmluZGluZy5pc190cmlnZ2VyZWRfYnkobW9kZSwgbW9kcywgJjMyKSk7CiAgICAvLyB9CgogICAgLy8gI1t0ZXN0XQogICAgLy8gZm4gYmluZGluZ190cmlnZ2VyX21vZHMoKSB7CiAgICAvLyAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZyB7CiAgICAvLyAgICAgICAgIG1vZHM6IE1vZGlmaWVyc1N0YXRlOjpBTFQgfCBNb2RpZmllcnNTdGF0ZTo6U1VQRVIsCiAgICAvLyAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgLy8gICAgIH07CgogICAgLy8gICAgIGxldCBzdXBlcnNldF9tb2RzID0gTW9kaWZpZXJzU3RhdGU6OmFsbCgpOwogICAgLy8gICAgIGxldCBzdWJzZXRfbW9kcyA9IE1vZGlmaWVyc1N0YXRlOjplbXB0eSgpOwoKICAgIC8vICAgICBsZXQgdCA9IGJpbmRpbmcudHJpZ2dlcjsKICAgIC8vICAgICBsZXQgbW9kZSA9IGJpbmRpbmcubW9kZTsKCiAgICAvLyAgICAgYXNzZXJ0IShiaW5kaW5nLmlzX3RyaWdnZXJlZF9ieShtb2RlLCBiaW5kaW5nLm1vZHMsICZ0KSk7CiAgICAvLyAgICAgYXNzZXJ0ISghYmluZGluZy5pc190cmlnZ2VyZWRfYnkobW9kZSwgc3VwZXJzZXRfbW9kcywgJnQpKTsKICAgIC8vICAgICBhc3NlcnQhKCFiaW5kaW5nLmlzX3RyaWdnZXJlZF9ieShtb2RlLCBzdWJzZXRfbW9kcywgJnQpKTsKICAgIC8vIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBiaW5kaW5nX3RyaWdnZXJfbW9kZXMoKSB7CiAgICAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG1vZGU6IEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBsZXQgdCA9IGJpbmRpbmcudHJpZ2dlcjsKICAgICAgICBsZXQgbW9kcyA9IGJpbmRpbmcubW9kczsKCiAgICAgICAgYXNzZXJ0ISghYmluZGluZy5pc190cmlnZ2VyZWRfYnkoQmluZGluZ01vZGU6OlZJLCBtb2RzLCAmdCkpOwogICAgICAgIGFzc2VydCEoYmluZGluZy5pc190cmlnZ2VyZWRfYnkoQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sIG1vZHMsICZ0KSk7CiAgICAgICAgYXNzZXJ0IShiaW5kaW5nLmlzX3RyaWdnZXJlZF9ieSgKICAgICAgICAgICAgQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4gfCBCaW5kaW5nTW9kZTo6VkksCiAgICAgICAgICAgIG1vZHMsCiAgICAgICAgICAgICZ0CiAgICAgICAgKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ190cmlnZ2VyX25vdG1vZGVzKCkgewogICAgICAgIGxldCBiaW5kaW5nID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBub3Rtb2RlOiBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgbGV0IHQgPSBiaW5kaW5nLnRyaWdnZXI7CiAgICAgICAgbGV0IG1vZHMgPSBiaW5kaW5nLm1vZHM7CgogICAgICAgIGFzc2VydCEoYmluZGluZy5pc190cmlnZ2VyZWRfYnkoQmluZGluZ01vZGU6OlZJLCBtb2RzLCAmdCkpOwogICAgICAgIGFzc2VydCEoIWJpbmRpbmcuaXNfdHJpZ2dlcmVkX2J5KEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLCBtb2RzLCAmdCkpOwogICAgICAgIGFzc2VydCEoIWJpbmRpbmcuaXNfdHJpZ2dlcmVkX2J5KAogICAgICAgICAgICBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiB8IEJpbmRpbmdNb2RlOjpWSSwKICAgICAgICAgICAgbW9kcywKICAgICAgICAgICAgJnQKICAgICAgICApKTsKICAgIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBiaW5kaW5nc19vdmVyd3JpdGUoKSB7CiAgICAgICAgbGV0IGJpbmRpbmdzID0gYmluZGluZ3MhKAogICAgICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICAgICAicSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpRdWl0OwogICAgICAgICAgICAiLCIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpDb25maWdFZGl0b3I7CiAgICAgICAgKTsKCiAgICAgICAgbGV0IGNvbmZpZ19iaW5kaW5ncyA9IHZlYyFbQ29uZmlnS2V5QmluZGluZyB7CiAgICAgICAgICAgIGtleTogU3RyaW5nOjpmcm9tKCJxIiksCiAgICAgICAgICAgIGFjdGlvbjogU3RyaW5nOjpmcm9tKCJyZWNlaXZlY2hhciIpLAogICAgICAgICAgICB3aXRoOiBTdHJpbmc6OmZyb20oInN1cGVyIiksCiAgICAgICAgICAgIGJ5dGVzOiB2ZWMhW10sCiAgICAgICAgICAgIHRleHQ6IFN0cmluZzo6ZnJvbSgiIiksCiAgICAgICAgICAgIG1vZGU6IFN0cmluZzo6ZnJvbSgiIiksCiAgICAgICAgfV07CgogICAgICAgIGxldCBuZXdfYmluZGluZ3MgPSBjb25maWdfa2V5X2JpbmRpbmdzKGNvbmZpZ19iaW5kaW5ncywgYmluZGluZ3MpOwoKICAgICAgICBhc3NlcnRfZXEhKG5ld19iaW5kaW5ncy5sZW4oKSwgMik7CiAgICAgICAgYXNzZXJ0X2VxIShuZXdfYmluZGluZ3NbMV0uYWN0aW9uLCBBY3Rpb246OlJlY2VpdmVDaGFyKTsKICAgIH0KfQoAAAAAAAAAAFX6AAAAAAAAAAAAAA", + "AQAAAAAAAAABAAAA+UcAAAAAAACRRwAAAAAAAAAAAAAAwFVA" + ] + ] + }, + { + "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context/grid.rs", + "redo_stack": + [ + [ + 242, + 1, + "insert", + { + "characters": "_" + }, + "AQAAAOs1AAAAAAAA6zUAAAAAAAABAAAAXw", + "AQAAAAAAAAABAAAA7DUAAAAAAADsNQAAAAAAAAAAAAAAAPC/" + ], + [ + 238, + 1, + "toggle_comment", + { + "block": false + }, + "AgAAAOc1AAAAAAAA6jUAAAAAAAAAAAAA5zUAAAAAAADnNQAAAAAAAAMAAAAvLyA", + "AQAAAAAAAAABAAAA9DUAAAAAAAD0NQAAAAAAAAAAAAAAAPC/" + ], + [ + 236, + 1, + "toggle_comment", + { + "block": false + }, + "AQAAAFg2AAAAAAAAWDYAAAAAAAADAAAALy8g", + "AQAAAAAAAAABAAAAbDYAAAAAAABsNgAAAAAAAAAAAAAAAPC/" + ] + ], + "settings": + { + "buffer_size": 122996, + "encoding": "UTF-8", + "line_ending": "Unix" + }, + "undo_stack": + [ + [ + 66, + 1, + "toggle_comment", + { + "block": false + }, + "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" + ], + [ + 75, + 1, + "toggle_comment", + { + "block": false + }, + "LwAAAEyLAAAAAAAATIsAAAAAAAADAAAALy8gPosAAAAAAAA+iwAAAAAAAAMAAAAvLyAriwAAAAAAACuLAAAAAAAAAwAAAC8vIAKLAAAAAAAAAosAAAAAAAADAAAALy8g3YoAAAAAAADdigAAAAAAAAMAAAAvLyCtigAAAAAAAK2KAAAAAAAAAwAAAC8vII6KAAAAAAAAjooAAAAAAAADAAAALy8gd4oAAAAAAAB3igAAAAAAAAMAAAAvLyBKigAAAAAAAEqKAAAAAAAAAwAAAC8vIAqKAAAAAAAACooAAAAAAAADAAAALy8g4IkAAAAAAADgiQAAAAAAAAMAAAAvLyCriQAAAAAAAKuJAAAAAAAAAwAAAC8vIHmJAAAAAAAAeYkAAAAAAAADAAAALy8gOYkAAAAAAAA5iQAAAAAAAAMAAAAvLyDeiAAAAAAAAN6IAAAAAAAAAwAAAC8vIKSIAAAAAAAApIgAAAAAAAADAAAALy8gaogAAAAAAABqiAAAAAAAAAMAAAAvLyAyiAAAAAAAADKIAAAAAAAAAwAAAC8vICSIAAAAAAAAJIgAAAAAAAADAAAALy8gAogAAAAAAAACiAAAAAAAAAMAAAAvLyDlhwAAAAAAAOWHAAAAAAAAAwAAAC8vIMyHAAAAAAAAzIcAAAAAAAADAAAALy8gqocAAAAAAACqhwAAAAAAAAMAAAAvLyCKhwAAAAAAAIqHAAAAAAAAAwAAAC8vIFyHAAAAAAAAXIcAAAAAAAADAAAALy8gP4cAAAAAAAA/hwAAAAAAAAMAAAAvLyAehwAAAAAAAB6HAAAAAAAAAwAAAC8vIOqGAAAAAAAA6oYAAAAAAAADAAAALy8gtIYAAAAAAAC0hgAAAAAAAAMAAAAvLyClhgAAAAAAAKWGAAAAAAAAAwAAAC8vIH2GAAAAAAAAfYYAAAAAAAADAAAALy8gaYYAAAAAAABphgAAAAAAAAMAAAAvLyBXhgAAAAAAAFeGAAAAAAAAAwAAAC8vIDiGAAAAAAAAOIYAAAAAAAADAAAALy8gGYYAAAAAAAAZhgAAAAAAAAMAAAAvLyD7hQAAAAAAAPuFAAAAAAAAAwAAAC8vINqFAAAAAAAA2oUAAAAAAAADAAAALy8gxIUAAAAAAADEhQAAAAAAAAMAAAAvLyCthQAAAAAAAK2FAAAAAAAAAwAAAC8vIHGFAAAAAAAAcYUAAAAAAAADAAAALy8gYoUAAAAAAABihQAAAAAAAAMAAAAvLyBEhQAAAAAAAESFAAAAAAAAAwAAAC8vICmFAAAAAAAAKYUAAAAAAAADAAAALy8gEoUAAAAAAAAShQAAAAAAAAMAAAAvLyDyhAAAAAAAAPKEAAAAAAAAAwAAAC8vIKmEAAAAAAAAqYQAAAAAAAADAAAALy8gmoQAAAAAAACahAAAAAAAAAMAAAAvLyA", + "AQAAAAAAAAABAAAAmoQAAAAAAABRiwAAAAAAAAAAAAAAAPC/" + ], + [ + 91, + 1, + "insert", + { + "characters": "\n\n" + }, + "BQAAAE82AAAAAAAAUDYAAAAAAAAAAAAAUDYAAAAAAABcNgAAAAAAAAAAAABcNgAAAAAAAF02AAAAAAAAAAAAAF02AAAAAAAAaTYAAAAAAAAAAAAAUDYAAAAAAABQNgAAAAAAAAwAAAAgICAgICAgICAgICA", + "AQAAAAAAAAABAAAATzYAAAAAAABPNgAAAAAAAP///////+9/" + ], + [ + 92, + 1, + "left_delete", + null, + "AQAAAFk2AAAAAAAAWTYAAAAAAAAEAAAAICAgIA", + "AQAAAAAAAAABAAAAXTYAAAAAAABdNgAAAAAAAAAAAAAAAPC/" + ], + [ + 93, + 1, + "insert", + { + "characters": "#" + }, + "AQAAAFk2AAAAAAAAWjYAAAAAAAAAAAAA", + "AQAAAAAAAAABAAAAWTYAAAAAAABZNgAAAAAAAAAAAAAAAPC/" + ], + [ + 103, + 1, + "insert_snippet", + { + "contents": "[$0]" + }, + "AQAAAFo2AAAAAAAAXDYAAAAAAAAAAAAA", + "AQAAAAAAAAABAAAAWjYAAAAAAABaNgAAAAAAAAAAAAAAAPC/" + ], + [ + 104, + 1, + "insert", + { + "characters": "c" + }, + "AQAAAFs2AAAAAAAAXDYAAAAAAAAAAAAA", + "AQAAAAAAAAABAAAAWzYAAAAAAABbNgAAAAAAAAAAAAAAAPC/" + ], + [ + 105, + 1, + "insert_completion", + { + "completion": "cfg", + "format": "text", + "keep_prefix": false, + "must_insert": false, + "trigger": "cfg" + }, + "AgAAAFs2AAAAAAAAWzYAAAAAAAABAAAAY1s2AAAAAAAAXjYAAAAAAAAAAAAA", + "AQAAAAAAAAABAAAAXDYAAAAAAABcNgAAAAAAAAAAAAAAAPC/" + ], + [ + 106, + 1, + "cut", + null, + "AQAAAFE2AAAAAAAAUTYAAAAAAAAPAAAAICAgICAgICAjW2NmZ10K", + "AQAAAAAAAAABAAAAXjYAAAAAAABeNgAAAAAAAAAAAAAAAPC/" + ], + [ + 110, + 1, + "left_delete", + null, + "AQAAAE82AAAAAAAATzYAAAAAAAABAAAACg", + "AQAAAAAAAAABAAAAUDYAAAAAAABQNgAAAAAAAAAAAAAAYGRA" + ] + ] + }, + { + "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context/mod.rs", + "settings": + { + "buffer_size": 40091, + "encoding": "UTF-8", + "line_ending": "Unix" + }, + "undo_stack": + [ + [ + 7, + 1, + "toggle_comment", + { + "block": false + }, + "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" + ], + [ + 8, + 1, + "toggle_comment", + { + "block": false + }, + "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" + ] + ] + } + ], + "build_system": "", + "build_system_choices": + [ + ], + "build_varint": "", + "command_palette": + { + "height": 0.0, + "last_filter": "", + "selected_items": + [ + [ + "pack", + "Package Control: Install Package" + ], + [ + "packa", + "Install Package Control" + ] + ], + "width": 0.0 + }, + "console": + { + "height": 0.0, + "history": + [ + ] + }, + "distraction_free": + { + "menu_visible": true, + "show_minimap": false, + "show_open_files": false, + "show_tabs": false, + "side_bar_visible": false, + "status_bar_visible": false + }, + "expanded_folders": + [ + "/Users/rapha/Documents/a/rio", + "/Users/rapha/Documents/a/rio/.cargo", + "/Users/rapha/Documents/a/rio/.github", + "/Users/rapha/Documents/a/rio/.github/workflows", + "/Users/rapha/Documents/a/rio/docs", + "/Users/rapha/Documents/a/rio/frontends", + "/Users/rapha/Documents/a/rio/frontends/rioterm", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/bindings", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context", + "/Users/rapha/Documents/a/rio/sugarloaf", + "/Users/rapha/Documents/a/rio/sugarloaf/examples", + "/Users/rapha/Documents/a/rio/sugarloaf/src", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text", + "/Users/rapha/Documents/a/rio/sugarloaf/src/context", + "/Users/rapha/Documents/a/rio/sugarloaf/src/layout", + "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf", + "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/compositors", + "/Users/rapha/Documents/a/rio/teletypewriter" + ], + "file_history": + [ + "/Users/rapha/Documents/a/rio/Cargo.toml", + "/Users/rapha/Documents/a/rio/.goreleaser.yaml", + "/Users/rapha/Documents/a/rio/.cargo/config.toml", + "/Users/rapha/Documents/a/rio/.github/workflows/nix-build.yml", + "/Users/rapha/Documents/a/rio/docs/docs/default-key-bindings.md", + "/Users/rapha/Documents/a/rio/misc/osx/Rio.app/Contents/Info.plist", + "/Users/rapha/Documents/a/rio/misc/windows/rio-x86_64.wxs", + "/Users/rapha/Documents/a/rio/misc/windows/rio-aarch64.wxs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/font_introspector/setting.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/font_introspector/scale/bitmap/png.rs", + "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/event.rs", + "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/appkit/event.rs", + "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/windows/keyboard.rs", + "/Users/rapha/Documents/a/sugarloaf/examples/text_with_doubled_line_height.rs", + "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/window_delegate.rs", + "/Users/rapha/Documents/a/rio/docs/docs/releases.md", + "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/appkit/cursor.rs", + "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/cursor.rs", + "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/linux/common/xkb/keymap.rs", + "/Users/rapha/Documents/a/rio/corcovado/src/poll.rs", + "/Users/rapha/Documents/a/rio/corcovado/src/stream.rs", + "/Users/rapha/Documents/a/rio/corcovado/src/sys/unix/io.rs", + "/Users/rapha/Documents/a/rio/copa/src/lib.rs", + "/Users/rapha/Documents/a/rio/corcovado/src/sys/unix/eventedfd.rs", + "/Users/rapha/Documents/a/rio/corcovado/src/timer.rs", + "/Users/rapha/Documents/a/rio/corcovado/test/mod.rs", + "/Users/rapha/Documents/a/rio/teletypewriter/src/unix/mod.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/config/colors/term.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/grid/mod.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/search.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/bindings/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/screen/hint.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/Cargo.toml", + "/Users/rapha/Documents/a/rio/sugarloaf/Cargo.toml", + "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/render_data.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/glyph/section/refed.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/image_cache/cache.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/image_cache/glyph.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/builder.rs", + "/Users/rapha/Documents/a/rio/Makefile", + "/Users/rapha/Documents/a/rio/rio-backend/src/config/keyboard.rs", + "/Users/rapha/Documents/a/rio/docs/docs/install/macos.md", + "/Users/rapha/Documents/a/rio/docs/docs/install/windows.md", + "/Users/rapha/Documents/a/rio/sugarloaf/src/font/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/compositors/advanced.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/builder.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/font_introspector/internal/head.rs", + "/Users/rapha/Documents/a/rio/.github/workflows/nightly.yml", + "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/state.rs", + "/Users/rapha/.config/rio/config.toml", + "/Users/rapha/Documents/a/rio/NOTES", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/screen/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/sequencer.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/text.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/layout_data.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/compositor.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/font/fallbacks/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/main.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/global.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/menu.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/menubar.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/router/window/mod.rs", + "/Users/rapha/Documents/a/winit/src/platform/macos.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/menuitem.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/app/menu/macos.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/app/route.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/router/mod.rs", + "/Users/rapha/Documents/a/rio/CHANGELOG.md", + "/Users/rapha/Documents/a/rio/.gitignore", + "/Users/rapha/Documents/a/rio/misc/windows/rio.wxs", + "/Users/rapha/Documents/a/rio/.github/workflows/release.yml", + "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/grid/row.rs", + "/Users/rapha/Documents/a/rio/rio-backend/Cargo.toml", + "/Users/rapha/Documents/a/rio/rio-backend/src/config/window.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/event/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/primitives.rs", + "/Users/rapha/Documents/a/rio/wa/src/native/macos.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/state/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/platform/mod.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/vi_mode.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/selection.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/routes/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/scheduler.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/constants.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/watcher.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/mouse/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/cross-winit/src/screen/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/context/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/routes/assistant.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/routes/dialog.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/routes/welcome.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/app/mod.rs", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src/state/navigation.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/graphics.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/layer/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/core.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/lib.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/ansi/sixel.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/ansi/graphics.rs", + "/Users/rapha/Documents/a/rio/rio-backend/src/performer/handler.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/core/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/pipeline.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rect/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/glyph/layout/font.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/glyph/layout/font.rs", + "/Users/rapha/Documents/a/rio/wa/src/event.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/image_cache/mod.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/tree.rs", + "/Users/rapha/Documents/a/rio/wa/src/native.rs", + "/Users/rapha/Documents/a/rio/wa/src/lib.rs", + "/Users/rapha/Documents/a/rio/wa/src/app/macos.rs", + "/Users/rapha/Documents/a/rio/corcovado/src/sys/unix/mod.rs", + "/Users/rapha/Documents/a/rio/corcovado/src/lib.rs", + "/Users/rapha/Documents/a/rio/docs/versioned_docs/version-0.0.x/install/macos.md", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/util/atomic.rs", + "/Users/rapha/Documents/a/rio/rust-toolchain.toml", + "/Users/rapha/Documents/a/rio/sugarloaf/src/font/loader/mod.rs", + "/Users/rapha/Documents/a/rio/corcovado/src/io.rs", + "/Users/rapha/Documents/a/rio/sugarloaf/src/font/fonts.rs", + "/Users/rapha/Documents/a/rio/corcovado/src/sys/unix/uio.rs" + ], + "find": + { + "height": 43.0 + }, + "find_in_files": + { + "height": 104.0, + "where_history": + [ + "/Users/rapha/Documents/a/rio/sugarloaf/src,", + "/Users/rapha/Documents/a/rio/sugarloaf/src/layout,", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text,", + "/Users/rapha/Documents/a/rio/sugarloaf/src/layout,", + "/Users/rapha/Documents/a/rio/sugarloaf,", + "/Users/rapha/Documents/a/rio/frontends,", + "/Users/rapha/Documents/a/rio,", + "/Users/rapha/Documents/a/rio/rio-backend,", + "/Users/rapha/Documents/a/rio/frontends/rioterm/src,", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components,", + "/Users/rapha/Documents/a/rio/wa/src,", + "/Users/rapha/Documents/a/rio/sugarloaf/src,", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components,", + "/Users/rapha/Documents/a/rio/sugarloaf/src,", + "/Users/rapha/Documents/a/rio/sugarloaf/src/components,", + "/Users/rapha/Documents/a/rio/sugarloaf/src,", + "/Users/rapha/Documents/a/rio/corcovado/src," + ] + }, + "find_state": + { + "case_sensitive": false, + "find_history": + [ + "create_mock_context", + "create_mock_context(", + "create_mock_context", + "{},\n", + "request_resize", + "val.me", + "val.", + "request_resize", + "messenger", + "self.inner[index].val.messenger", + "request_resize", + "test", + "request_resize", + "resize", + "test_resize", + "Toggle VI Mode ", + "ToggleViMode", + "platform_key_bindings", + "ToggleViMode", + "SearchForward", + "ToggleViMode", + "free", + "check", + "draw_layout", + "SugarCursor", + "cursor", + "FragmentStyleDecoration", + "layout", + "update_dimensions", + "dimensions", + "fetch_dimensions", + "line_height", + "ascent", + "fetch_dimensions", + "rect", + "line_h", + "2.2", + "", + "try_cursor_from_selector", + "et cls = NSCursor::class();", + "'a, ", + "a, ", + "rio", + "0xa", + "KeyCode::KeyV => Some(0x09),", + "contentRectForFrameRect", + "surface_position", + "v0.2.0", + "0.2.1", + "x86_64", + "1.15", + "clear", + "IS_MACOS", + "quan", + "famil", + "SugarTree", + "current", + " as usize", + "HashMap", + "HashSet", + "promoted", + "fonts_to_load", + "FontSource::Extension", + "id", + "isbn", + "promote", + "HashSet", + "Vec", + "Vec", + "shape", + "shape_item", + "upsert", + "HashSet", + "", + "Vec<(", + "Vec<", + ".clone()", + "font_data", + "fallbacks", + "fonts_to_load", + "scale =", + "needs_bidi", + "last_offset", + "needs_bidi", + "resolve", + "RenderData", + "render_data", + "as u32", + "u32, PathBuf", + "u32", + "load_from_font_source", + "PathBuf", + "Vec", + "HashSet", + "fonts_to_load", + "u32", + "HashSet", + "[u32]", + "fonts_to_load", + "ParagraphBuilder", + "FontDataExtensionVal", + "render_data", + "process_from_cache", + "next_", + "Borrow", + "Cow", + "IndexMut", + "font_by_id", + "as_ref", + "arc<", + "unwrap(", + "font_data_extension", + "FontLibraryData", + "FontLibrary", + "Font", + "[", + "load_from_font_source", + "font_data_extension", + "load_from_font_source", + "load_fon", + "droppa", + "hit", + "FontLibrary", + "FontDataExtension", + "Lazy", + "data:" + ], + "highlight": true, + "in_selection": false, + "preserve_case": false, + "regex": false, + "replace_history": + [ + "use_wa" + ], + "reverse": false, + "scrollbar_highlights": true, + "show_context": true, + "use_buffer2": true, + "use_gitignore": true, + "whole_word": false, + "wrap": true + }, + "folders": + [ + { + "path": "/Users/rapha/Documents/a/rio" + } + ], + "groups": + [ + { + "sheets": + [ + { + "buffer": 0, + "file": "/Users/rapha/Documents/a/rio/NOTES", + "semi_transient": false, + "settings": + { + "buffer_size": 565, + "regions": + { + }, + "selection": + [ + [ + 115, + 115 + ] + ], + "settings": + { + "syntax": "Packages/Text/Plain text.tmLanguage" + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "stack_index": 9, + "stack_multiselect": false, + "type": "text" + }, + { + "buffer": 1, + "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/mod.rs", + "semi_transient": false, + "settings": + { + "buffer_size": 22099, + "regions": + { + }, + "selection": + [ + [ + 16860, + 16860 + ] + ], + "settings": + { + "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", + "tab_size": 4, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "stack_index": 5, + "stack_multiselect": false, + "type": "text" + }, + { + "buffer": 2, + "file": "/Users/rapha/Documents/a/rio/pkgRio.nix", + "semi_transient": false, + "settings": + { + "buffer_size": 2578, + "regions": + { + }, + "selection": + [ + [ + 61, + 61 + ] + ], + "settings": + { + "syntax": "Packages/Text/Plain text.tmLanguage", + "tab_size": 2, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "stack_index": 4, + "stack_multiselect": false, + "type": "text" + }, + { + "buffer": 3, + "file": "/Users/rapha/Documents/a/rio/sugarloaf/examples/line_height.rs", + "semi_transient": false, + "settings": + { + "buffer_size": 11510, + "regions": + { + }, + "selection": + [ + [ + 11510, + 11510 + ] + ], + "settings": + { + "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", + "tab_size": 4, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "stack_index": 6, + "stack_multiselect": false, + "type": "text" + }, + { + "buffer": 4, + "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/content.rs", + "semi_transient": false, + "settings": + { + "buffer_size": 19461, + "regions": + { + }, + "selection": + [ + [ + 785, + 796 + ], + [ + 5883, + 5894 + ] + ], + "settings": + { + "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", + "tab_size": 4, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "stack_index": 7, + "stack_multiselect": false, + "type": "text" + }, + { + "buffer": 5, + "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/lib.rs", + "semi_transient": false, + "settings": + { + "buffer_size": 718, + "regions": + { + }, + "selection": + [ + [ + 336, + 336 + ] + ], + "settings": + { + "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", + "tab_size": 4, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "stack_index": 8, + "stack_multiselect": false, + "type": "text" + }, + { + "buffer": 6, + "file": "/Users/rapha/Documents/a/rio/sugarloaf/Cargo.toml", + "semi_transient": false, + "settings": + { + "buffer_size": 6744, + "regions": + { + }, + "selection": + [ + [ + 496, + 500 + ] + ], + "settings": + { + "syntax": "Packages/Text/Plain text.tmLanguage", + "tab_size": 4, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 0.0, + "zoom_level": 1.0 + }, + "stack_index": 3, + "stack_multiselect": false, + "type": "text" + }, + { + "buffer": 7, + "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/bindings/mod.rs", + "semi_transient": false, + "settings": + { + "buffer_size": 64085, + "regions": + { + }, + "selection": + [ + [ + 18425, + 18321 + ] + ], + "settings": + { + "allow_quiet_save": true, + "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", + "tab_size": 4, + "translate_tabs_to_spaces": true + }, + "translation.x": 28.5, + "translation.y": 12550.0, + "zoom_level": 1.0 + }, + "stack_index": 2, + "stack_multiselect": false, + "type": "text" + }, + { + "buffer": 8, + "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context/grid.rs", + "semi_transient": false, + "settings": + { + "buffer_size": 122996, + "regions": + { + }, + "selection": + [ + [ + 84155, + 84174 + ] + ], + "settings": + { + "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", + "tab_size": 4, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 52336.0, + "zoom_level": 1.0 + }, + "stack_index": 1, + "stack_multiselect": false, + "type": "text" + }, + { + "buffer": 9, + "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context/mod.rs", + "selected": true, + "semi_transient": false, + "settings": + { + "buffer_size": 40091, + "regions": + { + }, + "selection": + [ + [ + 5419, + 5438 + ] + ], + "settings": + { + "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", + "tab_size": 4, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 4076.0, + "zoom_level": 1.0 + }, + "stack_index": 0, + "stack_multiselect": false, + "type": "text" + } + ] + } + ], + "incremental_find": + { + "height": 31.0 + }, + "input": + { + "height": 43.0 + }, + "layout": + { + "cells": + [ + [ + 0, + 0, + 1, + 1 + ] + ], + "cols": + [ + 0.0, + 1.0 + ], + "rows": + [ + 0.0, + 1.0 + ] + }, + "menu_visible": true, + "output.find_results": + { + "height": 0.0 + }, + "pinned_build_system": "", + "project": "", + "replace": + { + "height": 58.0 + }, + "save_all_on_build": true, + "select_file": + { + "height": 0.0, + "last_filter": "", + "selected_items": + [ + [ + "docs/docs/default-key-bindings.md", + "docs/docs/default-key-bindings.md" + ], + [ + "Cargo.toml", + "Cargo.toml" + ], + [ + ".cargo/config.toml", + ".cargo/config.toml" + ], + [ + "scale/bitmap/png.rs", + "sugarloaf/src/font_introspector/scale/bitmap/png.rs" + ], + [ + "setting", + "sugarloaf/src/font_introspector/setting.rs" + ], + [ + "macos/cu", + "rio-window/src/platform_impl/macos/cursor.rs" + ], + [ + "appkit/cursor.rs", + "rio-window/src/platform_impl/macos/appkit/cursor.rs" + ], + [ + "xkb/keymap.rs", + "rio/rio-window/src/platform_impl/linux/common/xkb/keymap.rs" + ], + [ + "macos/eve", + "rio/rio-window/src/platform_impl/macos/event.rs" + ], + [ + "appkit/event.rs", + "rio/rio-window/src/platform_impl/macos/appkit/event.rs" + ], + [ + "windows/keyboard.rs", + "rio/rio-window/src/platform_impl/windows/keyboard.rs" + ], + [ + "awindow_delegate.rs", + "rio/rio-window/src/platform_impl/macos/window_delegate.rs" + ], + [ + "grid/ro", + "rio-backend/src/crosswords/grid/row.rs" + ], + [ + "grid/mod", + "rio-backend/src/crosswords/grid/mod.rs" + ], + [ + "", + "frontends/rioterm/src/app/mod.rs" + ], + [ + "rich_text/uti", + "sugarloaf/src/components/rich_text/util/atomic.rs" + ], + [ + "corcovado/src/po", + "corcovado/src/poll.rs" + ], + [ + "context/m", + "sugarloaf/src/context/mod.rs" + ] + ], + "width": 0.0 + }, + "select_project": + { + "height": 0.0, + "last_filter": "", + "selected_items": + [ + ], + "width": 0.0 + }, + "select_symbol": + { + "height": 0.0, + "last_filter": "", + "selected_items": + [ + ], + "width": 0.0 + }, + "selected_group": 0, + "settings": + { + }, + "show_minimap": true, + "show_open_files": false, + "show_tabs": true, + "side_bar_visible": true, + "side_bar_width": 299.0, + "status_bar_visible": true, + "template_settings": + { + } +} From 50dad1a95a50b503cb2bae320edf4284945deb42 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 17:08:00 -0300 Subject: [PATCH 13/20] does even pass? --- frontends/rioterm/src/context/grid.rs | 39 ++++++++++++++------------- frontends/rioterm/src/context/mod.rs | 1 - 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index 329c35b516..c77f865f39 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -1000,25 +1000,26 @@ pub mod test { rich_text_id, context_dimension, ); - // let context_width = context.dimension.width; - // let context_height = context.dimension.height; - // let context_margin = context.dimension.margin; - // let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); - // // The first context should fill completely w/h grid - // assert_eq!(grid.width, context_width); - // assert_eq!(grid.height, context_height); - - // // Context margin should empty - // assert_eq!(Delta::::default(), context_margin); - // assert_eq!(grid.margin, margin); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: rich_text_id, - // position: [10., 20.], - // })] - // ); + panic!("does even pass?"); + let context_width = context.dimension.width; + let context_height = context.dimension.height; + let context_margin = context.dimension.margin; + let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); + // The first context should fill completely w/h grid + assert_eq!(grid.width, context_width); + assert_eq!(grid.height, context_height); + + // Context margin should empty + assert_eq!(Delta::::default(), context_margin); + assert_eq!(grid.margin, margin); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: rich_text_id, + position: [10., 20.], + })] + ); } // #[test] diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index 005b4c279a..e30595dfb0 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -199,7 +199,6 @@ pub fn create_mock_context( let (sender, _receiver) = corcovado::channel::channel(); let messenger = Messenger::new(sender); let renderable_content = RenderableContent::new(Cursor::default()); - panic!("aaaa"); Context { route_id, From 2f4cabdbd45508dd01940e00986ad42a45a1429d Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 21:26:50 -0300 Subject: [PATCH 14/20] update markers --- frontends/rioterm/src/context/grid.rs | 307 +++++++++++++------------- 1 file changed, 153 insertions(+), 154 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index c77f865f39..4f5ff6cabc 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -969,183 +969,182 @@ pub mod test { use pretty_assertions::assert_eq; use rio_window::window::WindowId; - #[test] - fn test_single_context_respecting_margin_and_no_quad_creation() { - let margin = Delta { - x: 10., - top_y: 20., - bottom_y: 20., - }; - - let context_dimension = ContextDimension::build( - 1200.0, - 800.0, - SugarDimensions { - scale: 2., - width: 18., - height: 9., - }, - 1.0, - Delta::::default(), - ); - - assert_eq!(context_dimension.columns, 66); - assert_eq!(context_dimension.lines, 88); - let rich_text_id = 0; - let route_id = 0; - let context = create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ); - panic!("does even pass?"); - let context_width = context.dimension.width; - let context_height = context.dimension.height; - let context_margin = context.dimension.margin; - let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); - // The first context should fill completely w/h grid - assert_eq!(grid.width, context_width); - assert_eq!(grid.height, context_height); - - // Context margin should empty - assert_eq!(Delta::::default(), context_margin); - assert_eq!(grid.margin, margin); - - assert_eq!( - grid.objects(), - vec![Object::RichText(RichText { - id: rich_text_id, - position: [10., 20.], - })] - ); - } - // #[test] - // fn test_split_right() { + // fn test_single_context_respecting_margin_and_no_quad_creation() { // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., + // x: 10., + // top_y: 20., + // bottom_y: 20., // }; // let context_dimension = ContextDimension::build( // 1200.0, // 800.0, // SugarDimensions { - // scale: 1., - // width: 14., - // height: 8., + // scale: 2., + // width: 18., + // height: 9., // }, // 1.0, // Delta::::default(), // ); - // assert_eq!(context_dimension.columns, 85); - // assert_eq!(context_dimension.lines, 100); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + // assert_eq!(context_dimension.columns, 66); + // assert_eq!(context_dimension.lines, 88); + // let rich_text_id = 0; + // let route_id = 0; + // let context = create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ); + // let context_width = context.dimension.width; + // let context_height = context.dimension.height; + // let context_margin = context.dimension.margin; + // let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); + // // The first context should fill completely w/h grid + // assert_eq!(grid.width, context_width); + // assert_eq!(grid.height, context_height); + + // // Context margin should empty + // assert_eq!(Delta::::default(), context_margin); + // assert_eq!(grid.margin, margin); // assert_eq!( // grid.objects(), // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], + // id: rich_text_id, + // position: [10., 20.], // })] // ); - // grid.split_right(second_context); + // } - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [600., 0.0] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - // ] - // ); + #[test] + fn test_split_right() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; + let context_dimension = ContextDimension::build( + 1200.0, + 800.0, + SugarDimensions { + scale: 1., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); - // grid.split_right(third_context); + assert_eq!(context_dimension.columns, 85); + assert_eq!(context_dimension.lines, 100); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [600.0, 0.0] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [900.0, 0.0] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - // ] - // ); - // } + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + grid.split_right(second_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + Object::RichText(RichText { + id: second_context_id, + position: [600., 0.0] + }), + create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + ] + ); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + Object::RichText(RichText { + id: second_context_id, + position: [600.0, 0.0] + }), + create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), + Object::RichText(RichText { + id: third_context_id, + position: [900.0, 0.0] + }), + create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + ] + ); + } // #[test] // fn test_split_right_with_margin() { From 561a86b12d9e990491d0481edb091dcc0dacb5fb Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 21:56:10 -0300 Subject: [PATCH 15/20] remove args from nix build --- .github/workflows/nix-build.yml | 3 +- frontends/rioterm/src/context/grid.rs | 306 +++++++++++++------------- 2 files changed, 154 insertions(+), 155 deletions(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index 36088e338f..bd4c5f2b3f 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -24,5 +24,4 @@ jobs: - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - uses: DeterminateSystems/flake-checker-action@main - - name: Run `nix build` - run: nix build --max-jobs auto --build-max-jobs auto --print-build-logs + - run: nix build diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index 4f5ff6cabc..9a45fb344c 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -969,182 +969,182 @@ pub mod test { use pretty_assertions::assert_eq; use rio_window::window::WindowId; - // #[test] - // fn test_single_context_respecting_margin_and_no_quad_creation() { - // let margin = Delta { - // x: 10., - // top_y: 20., - // bottom_y: 20., - // }; - - // let context_dimension = ContextDimension::build( - // 1200.0, - // 800.0, - // SugarDimensions { - // scale: 2., - // width: 18., - // height: 9., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 66); - // assert_eq!(context_dimension.lines, 88); - // let rich_text_id = 0; - // let route_id = 0; - // let context = create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ); - // let context_width = context.dimension.width; - // let context_height = context.dimension.height; - // let context_margin = context.dimension.margin; - // let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); - // // The first context should fill completely w/h grid - // assert_eq!(grid.width, context_width); - // assert_eq!(grid.height, context_height); - - // // Context margin should empty - // assert_eq!(Delta::::default(), context_margin); - // assert_eq!(grid.margin, margin); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: rich_text_id, - // position: [10., 20.], - // })] - // ); - // } - #[test] - fn test_split_right() { + fn test_single_context_respecting_margin_and_no_quad_creation() { let margin = Delta { - x: 0., - top_y: 0., - bottom_y: 0., + x: 10., + top_y: 20., + bottom_y: 20., }; let context_dimension = ContextDimension::build( 1200.0, 800.0, SugarDimensions { - scale: 1., - width: 14., - height: 8., + scale: 2., + width: 18., + height: 9., }, 1.0, Delta::::default(), ); - assert_eq!(context_dimension.columns, 85); - assert_eq!(context_dimension.lines, 100); - - let (first_context, first_context_id) = { - let rich_text_id = 0; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let (second_context, second_context_id) = { - let rich_text_id = 1; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; - - let mut grid = - ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + assert_eq!(context_dimension.columns, 66); + assert_eq!(context_dimension.lines, 88); + let rich_text_id = 0; + let route_id = 0; + let context = create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ); + let context_width = context.dimension.width; + let context_height = context.dimension.height; + let context_margin = context.dimension.margin; + let grid = ContextGrid::::new(context, margin, [0., 0., 0., 0.]); + // The first context should fill completely w/h grid + assert_eq!(grid.width, context_width); + assert_eq!(grid.height, context_height); + + // Context margin should empty + assert_eq!(Delta::::default(), context_margin); + assert_eq!(grid.margin, margin); assert_eq!( grid.objects(), vec![Object::RichText(RichText { - id: first_context_id, - position: [0., 0.], + id: rich_text_id, + position: [10., 20.], })] ); - grid.split_right(second_context); + } - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - Object::RichText(RichText { - id: second_context_id, - position: [600., 0.0] - }), - create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - ] - ); + // #[test] + // fn test_split_right() { + // let margin = Delta { + // x: 0., + // top_y: 0., + // bottom_y: 0., + // }; - let (third_context, third_context_id) = { - let rich_text_id = 2; - let route_id = 0; - ( - create_mock_context( - VoidListener {}, - WindowId::from(0), - route_id, - rich_text_id, - context_dimension, - ), - rich_text_id, - ) - }; + // let context_dimension = ContextDimension::build( + // 1200.0, + // 800.0, + // SugarDimensions { + // scale: 1., + // width: 14., + // height: 8., + // }, + // 1.0, + // Delta::::default(), + // ); - grid.split_right(third_context); + // assert_eq!(context_dimension.columns, 85); + // assert_eq!(context_dimension.lines, 100); - assert_eq!( - grid.objects(), - vec![ - Object::RichText(RichText { - id: first_context_id, - position: [0.0, 0.0], - }), - create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - Object::RichText(RichText { - id: second_context_id, - position: [600.0, 0.0] - }), - create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), - Object::RichText(RichText { - id: third_context_id, - position: [900.0, 0.0] - }), - create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), - create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - ] - ); - } + // let (first_context, first_context_id) = { + // let rich_text_id = 0; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let (second_context, second_context_id) = { + // let rich_text_id = 1; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // let mut grid = + // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + // assert_eq!( + // grid.objects(), + // vec![Object::RichText(RichText { + // id: first_context_id, + // position: [0., 0.], + // })] + // ); + // grid.split_right(second_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [600., 0.0] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + // ] + // ); + + // let (third_context, third_context_id) = { + // let rich_text_id = 2; + // let route_id = 0; + // ( + // create_mock_context( + // VoidListener {}, + // WindowId::from(0), + // route_id, + // rich_text_id, + // context_dimension, + // ), + // rich_text_id, + // ) + // }; + + // grid.split_right(third_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + // Object::RichText(RichText { + // id: second_context_id, + // position: [600.0, 0.0] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), + // Object::RichText(RichText { + // id: third_context_id, + // position: [900.0, 0.0] + // }), + // create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), + // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + // ] + // ); + // } // #[test] // fn test_split_right_with_margin() { From a8acc24bf1665a1f814a95a71090640a41523365 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 22:00:59 -0300 Subject: [PATCH 16/20] create with config --- frontends/rioterm/src/context/mod.rs | 68 +++++++++++++++++++--------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index e30595dfb0..09343c3668 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -181,38 +181,62 @@ pub struct ContextManager { pub titles: ContextManagerTitles, } -pub fn create_mock_context( +pub fn create_mock_context( event_proxy: T, window_id: WindowId, route_id: usize, rich_text_id: usize, dimension: ContextDimension, ) -> Context { - let terminal = Crosswords::new( - dimension, - CursorShape::Block, - event_proxy, + let config = ContextManagerConfig { + #[cfg(not(target_os = "windows"))] + use_fork: true, + working_dir: None, + shell: Shell { + program: std::env::var("SHELL").unwrap_or("bash".to_string()), + args: vec![], + }, + spawn_performer: false, + is_native: false, + should_update_titles: false, + use_current_path: false, + split_color: [0., 0., 0., 0.], + }; + ContextManager::create_context( + (&Cursor::default(), false), + event_proxy.clone(), window_id, route_id, - ); - let terminal: Arc>> = Arc::new(FairMutex::new(terminal)); - let (sender, _receiver) = corcovado::channel::channel(); - let messenger = Messenger::new(sender); - let renderable_content = RenderableContent::new(Cursor::default()); - - Context { - route_id, - #[cfg(not(target_os = "windows"))] - main_fd: Arc::new(-1), - #[cfg(not(target_os = "windows"))] - shell_pid: 1, - messenger, - renderable_content, - terminal, rich_text_id, dimension, - ime: Ime::new(), - } + &config, + ).unwrap() + + // let terminal = Crosswords::new( + // dimension, + // CursorShape::Block, + // event_proxy, + // window_id, + // route_id, + // ); + // let terminal: Arc>> = Arc::new(FairMutex::new(terminal)); + // let (sender, _receiver) = corcovado::channel::channel(); + // let messenger = Messenger::new(sender); + // let renderable_content = RenderableContent::new(Cursor::default()); + + // Context { + // route_id, + // #[cfg(not(target_os = "windows"))] + // main_fd: Arc::new(-1), + // #[cfg(not(target_os = "windows"))] + // shell_pid: 1, + // messenger, + // renderable_content, + // terminal, + // rich_text_id, + // dimension, + // ime: Ime::new(), + // } } impl ContextManager { From f8aed06a20037bc5d4b60a9aef6ad311cedd6754 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 22:10:27 -0300 Subject: [PATCH 17/20] remove sublime worskapce --- rio-backend/src/config/rio.sublime-workspace | 2416 ------------------ 1 file changed, 2416 deletions(-) delete mode 100644 rio-backend/src/config/rio.sublime-workspace diff --git a/rio-backend/src/config/rio.sublime-workspace b/rio-backend/src/config/rio.sublime-workspace deleted file mode 100644 index 0cb8c7326b..0000000000 --- a/rio-backend/src/config/rio.sublime-workspace +++ /dev/null @@ -1,2416 +0,0 @@ -{ - "auto_complete": - { - "selected_items": - [ - [ - "Sug", - "SugarCursor" - ], - [ - "line", - "line_height" - ], - [ - "li", - "line_y" - ], - [ - "font_lo", - "fonts_to_load" - ], - [ - "fon", - "font_id" - ], - [ - "pri", - "println\tprintln!(…)" - ], - [ - "cl", - "clone" - ], - [ - "ex", - "extension" - ], - [ - "PRO", - "promoted" - ], - [ - "fo", - "font_id" - ], - [ - "font", - "font_data_extension" - ], - [ - "pr", - "println\tprintln!(…)" - ], - [ - "fonts_", - "fonts_to_load" - ], - [ - "u", - "usize" - ], - [ - "Font", - "FontSource" - ], - [ - "Fo", - "FontData" - ], - [ - "Has", - "HashSet" - ], - [ - "fonts_to", - "fonts_to_load" - ], - [ - "fonts", - "fonts_to_load" - ], - [ - "cle", - "clear" - ], - [ - "to", - "to_owned" - ], - [ - "font_d", - "font_data" - ], - [ - "FontLi", - "FontLibraryDataExtension" - ], - [ - "exe", - "extension_path" - ], - [ - "De", - "Default" - ], - [ - "FontD", - "FontDataLazy" - ], - [ - "dro", - "droppable" - ], - [ - "curr", - "current_font_id" - ], - [ - "font_", - "font_data" - ], - [ - "pa", - "path" - ], - [ - "is", - "is_emoji" - ], - [ - "da", - "data_ref" - ], - [ - "dat", - "data_ref" - ], - [ - "as", - "as_ref" - ], - [ - "by", - "font_by_id" - ], - [ - "fal", - "fallback" - ], - [ - "Pa", - "PathBuf" - ], - [ - "Fontda", - "FontDataLazy" - ], - [ - "to_", - "to_lowercase" - ], - [ - "in", - "into" - ], - [ - "con", - "context" - ], - [ - "scale", - "scale_context" - ], - [ - "Sca", - "ScaleContext" - ], - [ - "sca", - "scale_context" - ], - [ - "sc", - "scaler" - ], - [ - "win", - "window_id" - ], - [ - "wind", - "window_id" - ], - [ - "O", - "Option" - ], - [ - "proce", - "process_open_url" - ], - [ - "use", - "use_wa" - ], - [ - "us", - "use_wa" - ], - [ - "wi", - "window_id" - ], - [ - "rou", - "routes" - ], - [ - "red", - "redraw" - ], - [ - "Mod", - "ModifiersState" - ], - [ - "for", - "format" - ], - [ - "modi", - "modifiers_event" - ], - [ - "mod", - "modifiers" - ], - [ - "Key", - "KeyUp" - ], - [ - "Ke", - "KeyDown" - ], - [ - "Modi", - "Modifiers" - ], - [ - "pal", - "payload" - ], - [ - "po", - "point" - ], - [ - "hi", - "high_dpi" - ], - [ - "di", - "dimensions" - ], - [ - "re", - "return" - ], - [ - "cur", - "current" - ], - [ - "em", - "emoji" - ], - [ - "FON", - "font_data" - ], - [ - "Fon", - "FontData" - ], - [ - "cone", - "clone" - ], - [ - "fot", - "font_id" - ], - [ - "STYL", - "style" - ], - [ - "REG", - "FONT_ID_REGULAR" - ], - [ - "FontRe", - "FontDataRef" - ], - [ - "At", - "AtomicCounter" - ], - [ - "de", - "dead_code" - ] - ] - }, - "buffers": - [ - { - "file": "/Users/rapha/Documents/a/rio/NOTES", - "settings": - { - "buffer_size": 565, - "encoding": "UTF-8", - "line_ending": "Unix" - }, - "undo_stack": - [ - [ - 2, - 1, - "left_delete", - null, - "AQAAAAAAAAAAAAAAAAAAAAAAAADRAAAAIyAwLjEuMAoKLSBMaWdhdHVyYXMgcG9yIGNvbmZpZ3VyYWNhbwotIEFjZXJ0YXIgbyBzZWxlY3Rpb24KLSBBY2VydGFyIGxpbmsgKHVtYSB2ZXogZW5jb250cmFkbyBudW5jYSBtYWlzIG11ZGFyKQotIEZhemVyIHVtIGNhY2hlIHByYSBxdWFuZG8gcm9sYXIgbyBwcmVwYXJlICh0YSBsZXZhbmRvIGFzIHZlemVzIG1ldGFkZSBkbyB0ZW1wbyBwcmEgcmVuZGVyaXphcik", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAAAAAAAAAAANEAAAAAAAAAAAAAAAAA8L8" - ], - [ - 3, - 1, - "insert", - { - "characters": "-" - }, - "AQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8L8" - ], - [ - 4, - 1, - "insert", - { - "characters": " line-" - }, - "BgAAAAEAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAADAAAAAAAAAAAAAAADAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAABQAAAAAAAAAAAAAABQAAAAAAAAAGAAAAAAAAAAAAAAAGAAAAAAAAAAcAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAA8L8" - ], - [ - 5, - 1, - "insert", - { - "characters": "gh" - }, - "AgAAAAcAAAAAAAAACAAAAAAAAAAAAAAACAAAAAAAAAAJAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAHAAAAAAAAAAcAAAAAAAAAAAAAAAAA8L8" - ], - [ - 6, - 2, - "left_delete", - null, - "AgAAAAgAAAAAAAAACAAAAAAAAAABAAAAaAcAAAAAAAAABwAAAAAAAAABAAAAZw", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAJAAAAAAAAAAkAAAAAAAAAAAAAAAAA8L8" - ], - [ - 7, - 1, - "insert", - { - "characters": "height" - }, - "BgAAAAcAAAAAAAAACAAAAAAAAAAAAAAACAAAAAAAAAAJAAAAAAAAAAAAAAAJAAAAAAAAAAoAAAAAAAAAAAAAAAoAAAAAAAAACwAAAAAAAAAAAAAACwAAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAA0AAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAHAAAAAAAAAAcAAAAAAAAAAAAAAAAA8L8" - ], - [ - 13, - 1, - "insert", - { - "characters": "\n-" - }, - "AgAAAA0AAAAAAAAADgAAAAAAAAAAAAAADgAAAAAAAAAPAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAANAAAAAAAAAA0AAAAAAAAA////////738" - ], - [ - 14, - 1, - "insert", - { - "characters": " consertar" - }, - "CgAAAA8AAAAAAAAAEAAAAAAAAAAAAAAAEAAAAAAAAAARAAAAAAAAAAAAAAARAAAAAAAAABIAAAAAAAAAAAAAABIAAAAAAAAAEwAAAAAAAAAAAAAAEwAAAAAAAAAUAAAAAAAAAAAAAAAUAAAAAAAAABUAAAAAAAAAAAAAABUAAAAAAAAAFgAAAAAAAAAAAAAAFgAAAAAAAAAXAAAAAAAAAAAAAAAXAAAAAAAAABgAAAAAAAAAAAAAABgAAAAAAAAAGQAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAPAAAAAAAAAA8AAAAAAAAAAAAAAAAA8L8" - ], - [ - 15, - 1, - "insert", - { - "characters": " bug" - }, - "BAAAABkAAAAAAAAAGgAAAAAAAAAAAAAAGgAAAAAAAAAbAAAAAAAAAAAAAAAbAAAAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAHQAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAZAAAAAAAAABkAAAAAAAAAAAAAAAAA8L8" - ], - [ - 16, - 1, - "insert", - { - "characters": " no" - }, - "AwAAAB0AAAAAAAAAHgAAAAAAAAAAAAAAHgAAAAAAAAAfAAAAAAAAAAAAAAAfAAAAAAAAACAAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAdAAAAAAAAAB0AAAAAAAAAAAAAAAAA8L8" - ], - [ - 17, - 1, - "insert", - { - "characters": " yazi" - }, - "BQAAACAAAAAAAAAAIQAAAAAAAAAAAAAAIQAAAAAAAAAiAAAAAAAAAAAAAAAiAAAAAAAAACMAAAAAAAAAAAAAACMAAAAAAAAAJAAAAAAAAAAAAAAAJAAAAAAAAAAlAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAgAAAAAAAAACAAAAAAAAAAAAAAAAAA8L8" - ], - [ - 18, - 1, - "insert", - { - "characters": "\n-" - }, - "AgAAACUAAAAAAAAAJgAAAAAAAAAAAAAAJgAAAAAAAAAnAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlAAAAAAAAACUAAAAAAAAAAAAAAAAA8L8" - ], - [ - 19, - 1, - "insert", - { - "characters": " ca" - }, - "AwAAACcAAAAAAAAAKAAAAAAAAAAAAAAAKAAAAAAAAAApAAAAAAAAAAAAAAApAAAAAAAAACoAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAnAAAAAAAAACcAAAAAAAAAAAAAAAAA8L8" - ], - [ - 20, - 1, - "left_delete", - null, - "AQAAACkAAAAAAAAAKQAAAAAAAAABAAAAYQ", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAqAAAAAAAAACoAAAAAAAAAAAAAAAAA8L8" - ], - [ - 21, - 1, - "insert", - { - "characters": "haracter" - }, - "CAAAACkAAAAAAAAAKgAAAAAAAAAAAAAAKgAAAAAAAAArAAAAAAAAAAAAAAArAAAAAAAAACwAAAAAAAAAAAAAACwAAAAAAAAALQAAAAAAAAAAAAAALQAAAAAAAAAuAAAAAAAAAAAAAAAuAAAAAAAAAC8AAAAAAAAAAAAAAC8AAAAAAAAAMAAAAAAAAAAAAAAAMAAAAAAAAAAxAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAApAAAAAAAAACkAAAAAAAAAAAAAAAAA8L8" - ], - [ - 24, - 1, - "paste", - null, - "AgAAACgAAAAAAAAAMgAAAAAAAAAAAAAAMgAAAAAAAAAyAAAAAAAAAAkAAABjaGFyYWN0ZXI", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAxAAAAAAAAACgAAAAAAAAAAAAAAAAA8L8" - ], - [ - 26, - 1, - "insert", - { - "characters": " " - }, - "AQAAADIAAAAAAAAAMwAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAyAAAAAAAAADIAAAAAAAAAAAAAAAAA8L8" - ], - [ - 27, - 1, - "paste", - null, - "AQAAADMAAAAAAAAAXwAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAzAAAAAAAAADMAAAAAAAAAAAAAAAAA8L8" - ], - [ - 29, - 1, - "insert", - { - "characters": "\n\n" - }, - "AgAAAF8AAAAAAAAAYAAAAAAAAAAAAAAAYAAAAAAAAABhAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABfAAAAAAAAAF8AAAAAAAAAAAAAAAAA8L8" - ], - [ - 30, - 1, - "paste", - null, - "AQAAAGEAAAAAAAAAIQIAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABhAAAAAAAAAGEAAAAAAAAAAAAAAAAA8L8" - ], - [ - 33, - 1, - "insert", - { - "characters": "\n\n" - }, - "AgAAAGAAAAAAAAAAYQAAAAAAAAAAAAAAYQAAAAAAAABiAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABgAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAA" - ], - [ - 35, - 1, - "insert", - { - "characters": "Exa" - }, - "AwAAAGEAAAAAAAAAYgAAAAAAAAAAAAAAYgAAAAAAAABjAAAAAAAAAAAAAABjAAAAAAAAAGQAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABhAAAAAAAAAGEAAAAAAAAAAAAAAAAAAAA" - ], - [ - 36, - 1, - "left_delete", - null, - "AQAAAGMAAAAAAAAAYwAAAAAAAAABAAAAYQ", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABkAAAAAAAAAGQAAAAAAAAAAAAAAAAA8L8" - ], - [ - 37, - 1, - "insert", - { - "characters": "emplo" - }, - "BQAAAGMAAAAAAAAAZAAAAAAAAAAAAAAAZAAAAAAAAABlAAAAAAAAAAAAAABlAAAAAAAAAGYAAAAAAAAAAAAAAGYAAAAAAAAAZwAAAAAAAAAAAAAAZwAAAAAAAABoAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABjAAAAAAAAAGMAAAAAAAAAAAAAAAAA8L8" - ], - [ - 38, - 1, - "insert", - { - "characters": " do" - }, - "AwAAAGgAAAAAAAAAaQAAAAAAAAAAAAAAaQAAAAAAAABqAAAAAAAAAAAAAABqAAAAAAAAAGsAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABoAAAAAAAAAGgAAAAAAAAAAAAAAAAA8L8" - ], - [ - 39, - 1, - "insert", - { - "characters": " carlos:" - }, - "CAAAAGsAAAAAAAAAbAAAAAAAAAAAAAAAbAAAAAAAAABtAAAAAAAAAAAAAABtAAAAAAAAAG4AAAAAAAAAAAAAAG4AAAAAAAAAbwAAAAAAAAAAAAAAbwAAAAAAAABwAAAAAAAAAAAAAABwAAAAAAAAAHEAAAAAAAAAAAAAAHEAAAAAAAAAcgAAAAAAAAAAAAAAcgAAAAAAAABzAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABrAAAAAAAAAGsAAAAAAAAAAAAAAAAA8L8" - ] - ] - }, - { - "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/mod.rs", - "settings": - { - "buffer_size": 22099, - "line_ending": "Unix" - }, - "undo_stack": - [ - [ - 36, - 1, - "toggle_comment", - { - "block": false - }, - "AQAAANFAAAAAAAAA1EAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADjQAAAAAAAAP1AAAAAAAAAAAAAAAAA8L8" - ], - [ - 42, - 1, - "insert", - { - "characters": "\n" - }, - "AgAAAAFBAAAAAAAAAkEAAAAAAAAAAAAAAkEAAAAAAAAKQQAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAABQQAAAAAAAAFBAAAAAAAAAAAAAAAA8L8" - ], - [ - 43, - 1, - "paste", - null, - "AQAAAApBAAAAAAAAOkEAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAKQQAAAAAAAApBAAAAAAAAAAAAAAAA8L8" - ], - [ - 44, - 1, - "toggle_comment", - { - "block": false - }, - "AQAAAApBAAAAAAAACkEAAAAAAAADAAAALy8g", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAA6QQAAAAAAADpBAAAAAAAAAAAAAAAA8L8" - ], - [ - 47, - 1, - "left_delete", - null, - "AQAAABxBAAAAAAAAHEEAAAAAAAAaAAAAYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAA2QQAAAAAAABxBAAAAAAAAAAAAAAAA8L8" - ], - [ - 48, - 1, - "insert", - { - "characters": "rect.e" - }, - "BgAAABxBAAAAAAAAHUEAAAAAAAAAAAAAHUEAAAAAAAAeQQAAAAAAAAAAAAAeQQAAAAAAAB9BAAAAAAAAAAAAAB9BAAAAAAAAIEEAAAAAAAAAAAAAIEEAAAAAAAAhQQAAAAAAAAAAAAAhQQAAAAAAACJBAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAcQQAAAAAAABxBAAAAAAAAAAAAAAAA8L8" - ], - [ - 49, - 1, - "left_delete", - null, - "AQAAACFBAAAAAAAAIUEAAAAAAAABAAAAZQ", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAiQQAAAAAAACJBAAAAAAAAAAAAAAAA8L8" - ], - [ - 50, - 1, - "insert", - { - "characters": "he" - }, - "AgAAACFBAAAAAAAAIkEAAAAAAAAAAAAAIkEAAAAAAAAjQQAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAhQQAAAAAAACFBAAAAAAAAAAAAAAAA8L8" - ], - [ - 51, - 1, - "insert_completion", - { - "completion": "height", - "format": "text", - "keep_prefix": false, - "must_insert": false, - "trigger": "height" - }, - "AgAAACFBAAAAAAAAIUEAAAAAAAACAAAAaGUhQQAAAAAAACdBAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAjQQAAAAAAACNBAAAAAAAAAAAAAAAA8L8" - ], - [ - 56, - 1, - "toggle_comment", - { - "block": false - }, - "AQAAABVAAAAAAAAAGEAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAtQAAAAAAAAC1AAAAAAAAAAAAAAAAA8L8" - ], - [ - 76, - 1, - "toggle_comment", - { - "block": false - }, - "AQAAAJZAAAAAAAAAmUAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACxQAAAAAAAAKpAAAAAAAAAAAAAAAAA8L8" - ], - [ - 78, - 1, - "insert", - { - "characters": "\nli" - }, - "BAAAALVAAAAAAAAAtkAAAAAAAAAAAAAAtkAAAAAAAAC+QAAAAAAAAAAAAAC+QAAAAAAAAL9AAAAAAAAAAAAAAL9AAAAAAAAAwEAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAC1QAAAAAAAALVAAAAAAAAA////////738" - ], - [ - 84, - 1, - "insert_completion", - { - "completion": "line_y", - "format": "text", - "keep_prefix": false, - "must_insert": false, - "trigger": "line_y" - }, - "AgAAAL5AAAAAAAAAvkAAAAAAAAACAAAAbGm+QAAAAAAAAMRAAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADAQAAAAAAAAMBAAAAAAAAAAAAAAAAA8L8" - ], - [ - 85, - 1, - "insert", - { - "characters": " =" - }, - "AgAAAMRAAAAAAAAAxUAAAAAAAAAAAAAAxUAAAAAAAADGQAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADEQAAAAAAAAMRAAAAAAAAAAAAAAAAA8L8" - ], - [ - 86, - 1, - "insert", - { - "characters": " " - }, - "AQAAAMZAAAAAAAAAx0AAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADGQAAAAAAAAMZAAAAAAAAAAAAAAAAA8L8" - ], - [ - 87, - 1, - "paste", - null, - "AQAAAMdAAAAAAAAA0kAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADHQAAAAAAAAMdAAAAAAAAAAAAAAAAA8L8" - ], - [ - 93, - 1, - "insert", - { - "characters": "l" - }, - "AQAAAMdAAAAAAAAAyEAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADHQAAAAAAAAMdAAAAAAAAAAAAAAAAA8L8" - ], - [ - 94, - 1, - "insert", - { - "characters": " " - }, - "AQAAAMhAAAAAAAAAyUAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADIQAAAAAAAAMhAAAAAAAAAAAAAAAAA8L8" - ], - [ - 96, - 1, - "insert", - { - "characters": "in" - }, - "AgAAAMhAAAAAAAAAyUAAAAAAAAAAAAAAyUAAAAAAAADKQAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADIQAAAAAAAAMhAAAAAAAAAAAAAAAAA8L8" - ], - [ - 97, - 1, - "insert_completion", - { - "completion": "line_y", - "format": "text", - "keep_prefix": false, - "must_insert": false, - "trigger": "line_y" - }, - "AgAAAMdAAAAAAAAAx0AAAAAAAAADAAAAbGlux0AAAAAAAADNQAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADKQAAAAAAAAMpAAAAAAAAAAAAAAAAA8L8" - ], - [ - 98, - 1, - "insert", - { - "characters": " +" - }, - "AgAAAM1AAAAAAAAAzkAAAAAAAAAAAAAAzkAAAAAAAADPQAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADNQAAAAAAAAM1AAAAAAAAAAAAAAAAA8L8" - ], - [ - 100, - 1, - "insert", - { - "characters": ";" - }, - "AQAAANtAAAAAAAAA3EAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADbQAAAAAAAANtAAAAAAAAA////////738" - ], - [ - 102, - 1, - "toggle_comment", - { - "block": false - }, - "AQAAAG5AAAAAAAAAcUAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACMQAAAAAAAAIxAAAAAAAAAAAAAAADAeUA" - ], - [ - 105, - 1, - "toggle_comment", - { - "block": false - }, - "AQAAAOQ/AAAAAAAA5z8AAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAFQAAAAAAAAAVAAAAAAAAAAAAAAADAe0A" - ], - [ - 117, - 1, - "insert", - { - "characters": "rect." - }, - "BgAAAHpEAAAAAAAAe0QAAAAAAAAAAAAAe0QAAAAAAAB7RAAAAAAAAAYAAABhc2NlbnR7RAAAAAAAAHxEAAAAAAAAAAAAAHxEAAAAAAAAfUQAAAAAAAAAAAAAfUQAAAAAAAB+RAAAAAAAAAAAAAB+RAAAAAAAAH9EAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB6RAAAAAAAAIBEAAAAAAAAAAAAAAAA8L8" - ], - [ - 118, - 1, - "insert_completion", - { - "completion": "height", - "format": "text", - "keep_prefix": false, - "must_insert": true, - "trigger": "height" - }, - "AQAAAH9EAAAAAAAAhUQAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB/RAAAAAAAAH9EAAAAAAAAAAAAAAAA8L8" - ], - [ - 121, - 1, - "toggle_comment", - { - "block": false - }, - "AQAAALU/AAAAAAAAuD8AAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADMPwAAAAAAAMw/AAAAAAAAAAAAAAAA8L8" - ], - [ - 124, - 1, - "revert", - null, - "AgAAAAAAAAAAAAAAAAAAAAAAAAC4VgAAbW9kIGJhdGNoOwptb2QgY29tcG9zaXRvcjsKbW9kIGltYWdlX2NhY2hlOwpwdWIgbW9kIHRleHQ7Cgp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OmNvcmU6Om9ydGhvZ3JhcGhpY19wcm9qZWN0aW9uOwp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OnJpY2hfdGV4dDo6aW1hZ2VfY2FjaGU6OntHbHlwaENhY2hlLCBJbWFnZUNhY2hlfTsKdXNlIGNyYXRlOjpjb250ZXh0OjpDb250ZXh0Owp1c2UgY3JhdGU6OmZvbnQ6OkZvbnRMaWJyYXJ5Owp1c2UgY3JhdGU6OmxheW91dDo6U3VnYXJEaW1lbnNpb25zOwp1c2UgY3JhdGU6OnN1Z2FybG9hZjo6Z3JhcGhpY3M6OkdyYXBoaWNSZW5kZXJSZXF1ZXN0Owp1c2UgY3JhdGU6OkdyYXBoaWNzOwp1c2UgY29tcG9zaXRvcjo6e0NvbXBvc2l0b3IsIERpc3BsYXlMaXN0LCBSZWN0LCBWZXJ0ZXh9Owp1c2Ugc3RkOjpjb2xsZWN0aW9uczo6SGFzaFNldDsKdXNlIHN0ZDo6e2JvcnJvdzo6Q293LCBtZW19Owp1c2UgdGV4dDo6e0dseXBoLCBUZXh0UnVuU3R5bGV9Owp1c2Ugd2dwdTo6dXRpbDo6RGV2aWNlRXh0OwoKLy8gTm90ZTogY3VycmVudGx5IGl0J3MgdXNpbmcgSW5kZXhlZCBkcmF3aW5nIGluc3RlYWQgb2YgSW5zdGFuY2UgZHJhd2luZyBjb3VsZCBiZSB3b3J0aCB0bwovLyBldmFsdWF0ZSBpZiB3b3VsZCBtYWtlIHNlbnNlIG1vdmUgdG8gaW5zdGFuY2UgZHJhd2luZyBpbnN0ZWFkCi8vIGh0dHBzOi8vbWF0aC5od3MuZWR1L2dyYXBoaWNzYm9vay9jOS9zMi5odG1sCi8vIGh0dHBzOi8vZG9jcy5ycy93Z3B1L2xhdGVzdC93Z3B1L2VudW0uVmVydGV4U3RlcE1vZGUuaHRtbAoKcHViIGNvbnN0IEJMRU5EOiBPcHRpb248d2dwdTo6QmxlbmRTdGF0ZT4gPSBTb21lKHdncHU6OkJsZW5kU3RhdGUgewogICAgY29sb3I6IHdncHU6OkJsZW5kQ29tcG9uZW50IHsKICAgICAgICBzcmNfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6U3JjQWxwaGEsCiAgICAgICAgZHN0X2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZU1pbnVzU3JjQWxwaGEsCiAgICAgICAgb3BlcmF0aW9uOiB3Z3B1OjpCbGVuZE9wZXJhdGlvbjo6QWRkLAogICAgfSwKICAgIGFscGhhOiB3Z3B1OjpCbGVuZENvbXBvbmVudCB7CiAgICAgICAgc3JjX2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZSwKICAgICAgICBkc3RfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6T25lTWludXNTcmNBbHBoYSwKICAgICAgICBvcGVyYXRpb246IHdncHU6OkJsZW5kT3BlcmF0aW9uOjpBZGQsCiAgICB9LAp9KTsKCnB1YiBzdHJ1Y3QgUmljaFRleHRCcnVzaCB7CiAgICB2ZXJ0ZXhfYnVmZmVyOiB3Z3B1OjpCdWZmZXIsCiAgICBjb25zdGFudF9iaW5kX2dyb3VwOiB3Z3B1OjpCaW5kR3JvdXAsCiAgICBsYXlvdXRfYmluZF9ncm91cDogd2dwdTo6QmluZEdyb3VwLAogICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0OiB3Z3B1OjpCaW5kR3JvdXBMYXlvdXQsCiAgICB0cmFuc2Zvcm06IHdncHU6OkJ1ZmZlciwKICAgIHBpcGVsaW5lOiB3Z3B1OjpSZW5kZXJQaXBlbGluZSwKICAgIGluZGV4X2J1ZmZlcjogd2dwdTo6QnVmZmVyLAogICAgaW5kZXhfYnVmZmVyX3NpemU6IHU2NCwKICAgIGN1cnJlbnRfdHJhbnNmb3JtOiBbZjMyOyAxNl0sCiAgICBjb21wOiBDb21wb3NpdG9yLAogICAgZGxpc3Q6IERpc3BsYXlMaXN0LAogICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXI6IHVzaXplLAogICAgdGV4dHVyZXNfdmVyc2lvbjogdXNpemUsCiAgICBpbWFnZXM6IEltYWdlQ2FjaGUsCiAgICBnbHlwaHM6IEdseXBoQ2FjaGUsCn0KCmltcGwgUmljaFRleHRCcnVzaCB7CiAgICBwdWIgZm4gbmV3KGNvbnRleHQ6ICZDb250ZXh0KSAtPiBTZWxmIHsKICAgICAgICBsZXQgZGV2aWNlID0gJmNvbnRleHQuZGV2aWNlOwogICAgICAgIGxldCBkbGlzdCA9IERpc3BsYXlMaXN0OjpuZXcoKTsKICAgICAgICBsZXQgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIgPSAyXzAwMDsKCiAgICAgICAgbGV0IGN1cnJlbnRfdHJhbnNmb3JtID0KICAgICAgICAgICAgb3J0aG9ncmFwaGljX3Byb2plY3Rpb24oY29udGV4dC5zaXplLndpZHRoLCBjb250ZXh0LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtID0gZGV2aWNlLmNyZWF0ZV9idWZmZXJfaW5pdCgmd2dwdTo6dXRpbDo6QnVmZmVySW5pdERlc2NyaXB0b3IgewogICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgY29udGVudHM6IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZjdXJyZW50X3RyYW5zZm9ybSksCiAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlVOSUZPUk0gfCB3Z3B1OjpCdWZmZXJVc2FnZXM6OkNPUFlfRFNULAogICAgICAgIH0pOwoKICAgICAgICAvLyBDcmVhdGUgcGlwZWxpbmUgbGF5b3V0CiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9iaW5kX2dyb3VwX2xheW91dCgmd2dwdTo6QmluZEdyb3VwTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbCiAgICAgICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwTGF5b3V0RW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmlsaXR5OiB3Z3B1OjpTaGFkZXJTdGFnZXM6OlZFUlRFWCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpCdWZmZXIgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJ1ZmZlckJpbmRpbmdUeXBlOjpVbmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzX2R5bmFtaWNfb2Zmc2V0OiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9iaW5kaW5nX3NpemU6IHdncHU6OkJ1ZmZlclNpemU6Om5ldyhtZW06OnNpemVfb2Y6OjwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZjMyOyAxNl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzIHdncHU6OkJ1ZmZlckFkZHJlc3MpLAogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogTm9uZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgYmluZGluZzogMSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogd2dwdTo6U2hhZGVyU3RhZ2VzOjpWRVJURVgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgd2dwdTo6U2hhZGVyU3RhZ2VzOjpGUkFHTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpTYW1wbGVyKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2dwdTo6U2FtcGxlckJpbmRpbmdUeXBlOjpGaWx0ZXJpbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGxheW91dF9iaW5kX2dyb3VwX2xheW91dCA9CiAgICAgICAgICAgIGRldmljZS5jcmVhdGVfYmluZF9ncm91cF9sYXlvdXQoJndncHU6OkJpbmRHcm91cExheW91dERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgICAgICBlbnRyaWVzOiAmW3dncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6IHdncHU6OlNoYWRlclN0YWdlczo6RlJBR01FTlQsCiAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpUZXh0dXJlIHsKICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX3R5cGU6IHdncHU6OlRleHR1cmVTYW1wbGVUeXBlOjpGbG9hdCB7IGZpbHRlcmFibGU6IHRydWUgfSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlld19kaW1lbnNpb246IHdncHU6OlRleHR1cmVWaWV3RGltZW5zaW9uOjpEMiwKICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlzYW1wbGVkOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgIH0pOwoKICAgICAgICBsZXQgcGlwZWxpbmVfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9waXBlbGluZV9sYXlvdXQoJndncHU6OlBpcGVsaW5lTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIHB1c2hfY29uc3RhbnRfcmFuZ2VzOiAmW10sCiAgICAgICAgICAgICAgICBiaW5kX2dyb3VwX2xheW91dHM6ICZbCiAgICAgICAgICAgICAgICAgICAgJmNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgICZsYXlvdXRfYmluZF9ncm91cF9sYXlvdXQsCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGltYWdlcyA9IEltYWdlQ2FjaGU6Om5ldyhjb250ZXh0KTsKCiAgICAgICAgbGV0IHNhbXBsZXIgPSBkZXZpY2UuY3JlYXRlX3NhbXBsZXIoJndncHU6OlNhbXBsZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3U6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3Y6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3c6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgbWFnX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWluX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWlwbWFwX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbG9kX21pbl9jbGFtcDogMGYzMiwKICAgICAgICAgICAgbG9kX21heF9jbGFtcDogMGYzMiwKICAgICAgICAgICAgLi5EZWZhdWx0OjpkZWZhdWx0KCkKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXAgPSBkZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICBsYXlvdXQ6ICZjb25zdGFudF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlsKICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHJlc291cmNlOiB3Z3B1OjpCaW5kaW5nUmVzb3VyY2U6OkJ1ZmZlcih3Z3B1OjpCdWZmZXJCaW5kaW5nIHsKICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiAmdHJhbnNmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgIGJpbmRpbmc6IDEsCiAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6U2FtcGxlcigmc2FtcGxlciksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICBdLAogICAgICAgICAgICBsYWJlbDogU29tZSgicmljaF90ZXh0Ojpjb25zdGFudF9iaW5kX2dyb3VwIiksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBsYXlvdXRfYmluZF9ncm91cCA9IGRldmljZS5jcmVhdGVfYmluZF9ncm91cCgmd2dwdTo6QmluZEdyb3VwRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxheW91dDogJmxheW91dF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlt3Z3B1OjpCaW5kR3JvdXBFbnRyeSB7CiAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6VGV4dHVyZVZpZXcoJmltYWdlcy50ZXh0dXJlX3ZpZXcpLAogICAgICAgICAgICB9XSwKICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6bGF5b3V0X2JpbmRfZ3JvdXAiKSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHNoYWRlciA9IGRldmljZS5jcmVhdGVfc2hhZGVyX21vZHVsZSh3Z3B1OjpTaGFkZXJNb2R1bGVEZXNjcmlwdG9yIHsKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIHNvdXJjZTogd2dwdTo6U2hhZGVyU291cmNlOjpXZ3NsKENvdzo6Qm9ycm93ZWQoaW5jbHVkZV9zdHIhKAogICAgICAgICAgICAgICAgInJpY2hfdGV4dC53Z3NsIgogICAgICAgICAgICApKSksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBwaXBlbGluZSA9IGRldmljZS5jcmVhdGVfcmVuZGVyX3BpcGVsaW5lKCZ3Z3B1OjpSZW5kZXJQaXBlbGluZURlc2NyaXB0b3IgewogICAgICAgICAgICBjYWNoZTogTm9uZSwKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIGxheW91dDogU29tZSgmcGlwZWxpbmVfbGF5b3V0KSwKICAgICAgICAgICAgdmVydGV4OiB3Z3B1OjpWZXJ0ZXhTdGF0ZSB7CiAgICAgICAgICAgICAgICBjb21waWxhdGlvbl9vcHRpb25zOiB3Z3B1OjpQaXBlbGluZUNvbXBpbGF0aW9uT3B0aW9uczo6ZGVmYXVsdCgpLAogICAgICAgICAgICAgICAgbW9kdWxlOiAmc2hhZGVyLAogICAgICAgICAgICAgICAgZW50cnlfcG9pbnQ6IFNvbWUoInZzX21haW4iKSwKICAgICAgICAgICAgICAgIGJ1ZmZlcnM6ICZbd2dwdTo6VmVydGV4QnVmZmVyTGF5b3V0IHsKICAgICAgICAgICAgICAgICAgICBhcnJheV9zdHJpZGU6IG1lbTo6c2l6ZV9vZjo6PFZlcnRleD4oKSBhcyB1NjQsCiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLnJzL3dncHUvbGF0ZXN0L3dncHUvZW51bS5WZXJ0ZXhTdGVwTW9kZS5odG1sCiAgICAgICAgICAgICAgICAgICAgc3RlcF9tb2RlOiB3Z3B1OjpWZXJ0ZXhTdGVwTW9kZTo6VmVydGV4LAogICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6ICZ3Z3B1Ojp2ZXJ0ZXhfYXR0cl9hcnJheSEoCiAgICAgICAgICAgICAgICAgICAgICAgIDAgPT4gRmxvYXQzMngzLAogICAgICAgICAgICAgICAgICAgICAgICAxID0+IEZsb2F0MzJ4NCwKICAgICAgICAgICAgICAgICAgICAgICAgMiA9PiBGbG9hdDMyeDIsCiAgICAgICAgICAgICAgICAgICAgICAgIDMgPT4gU2ludDMyeDIsCiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIH1dLAogICAgICAgICAgICB9LAogICAgICAgICAgICBmcmFnbWVudDogU29tZSh3Z3B1OjpGcmFnbWVudFN0YXRlIHsKICAgICAgICAgICAgICAgIGNvbXBpbGF0aW9uX29wdGlvbnM6IHdncHU6OlBpcGVsaW5lQ29tcGlsYXRpb25PcHRpb25zOjpkZWZhdWx0KCksCiAgICAgICAgICAgICAgICBtb2R1bGU6ICZzaGFkZXIsCiAgICAgICAgICAgICAgICBlbnRyeV9wb2ludDogU29tZSgiZnNfbWFpbiIpLAogICAgICAgICAgICAgICAgdGFyZ2V0czogJltTb21lKHdncHU6OkNvbG9yVGFyZ2V0U3RhdGUgewogICAgICAgICAgICAgICAgICAgIGZvcm1hdDogY29udGV4dC5mb3JtYXQsCiAgICAgICAgICAgICAgICAgICAgYmxlbmQ6IEJMRU5ELAogICAgICAgICAgICAgICAgICAgIHdyaXRlX21hc2s6IHdncHU6OkNvbG9yV3JpdGVzOjpBTEwsCiAgICAgICAgICAgICAgICB9KV0sCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICBwcmltaXRpdmU6IHdncHU6OlByaW1pdGl2ZVN0YXRlIHsKICAgICAgICAgICAgICAgIHRvcG9sb2d5OiB3Z3B1OjpQcmltaXRpdmVUb3BvbG9neTo6VHJpYW5nbGVMaXN0LAogICAgICAgICAgICAgICAgc3RyaXBfaW5kZXhfZm9ybWF0OiBOb25lLAogICAgICAgICAgICAgICAgZnJvbnRfZmFjZTogd2dwdTo6RnJvbnRGYWNlOjpDY3csCiAgICAgICAgICAgICAgICBjdWxsX21vZGU6IE5vbmUsCiAgICAgICAgICAgICAgICBwb2x5Z29uX21vZGU6IHdncHU6OlBvbHlnb25Nb2RlOjpGaWxsLAogICAgICAgICAgICAgICAgdW5jbGlwcGVkX2RlcHRoOiBmYWxzZSwKICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZTogZmFsc2UsCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGRlcHRoX3N0ZW5jaWw6IE5vbmUsCiAgICAgICAgICAgIG11bHRpc2FtcGxlOiB3Z3B1OjpNdWx0aXNhbXBsZVN0YXRlOjpkZWZhdWx0KCksCiAgICAgICAgICAgIG11bHRpdmlldzogTm9uZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHZlcnRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6Okluc3RhbmNlcyBCdWZmZXIiKSwKICAgICAgICAgICAgc2l6ZTogbWVtOjpzaXplX29mOjo8VmVydGV4PigpIGFzIHU2NCAqIHN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgdXNhZ2U6IHdncHU6OkJ1ZmZlclVzYWdlczo6VkVSVEVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgbWFwcGVkX2F0X2NyZWF0aW9uOiBmYWxzZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplOiAmW3UzMl0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmZGxpc3QuaW5kaWNlcyk7CiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplID0gaW5kZXhfYnVmZmVyX3NpemUubGVuKCkgYXMgdTY0OwogICAgICAgIGxldCBpbmRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6OkluZGljZXMgQnVmZmVyIiksCiAgICAgICAgICAgIHNpemU6IGluZGV4X2J1ZmZlcl9zaXplLAogICAgICAgICAgICB1c2FnZTogd2dwdTo6QnVmZmVyVXNhZ2VzOjpJTkRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogZmFsc2UsCiAgICAgICAgfSk7CgogICAgICAgIFJpY2hUZXh0QnJ1c2ggewogICAgICAgICAgICBsYXlvdXRfYmluZF9ncm91cCwKICAgICAgICAgICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICBjb25zdGFudF9iaW5kX2dyb3VwLAogICAgICAgICAgICBpbmRleF9idWZmZXJfc2l6ZSwKICAgICAgICAgICAgaW5kZXhfYnVmZmVyLAogICAgICAgICAgICBjb21wOiBDb21wb3NpdG9yOjpuZXcoKSwKICAgICAgICAgICAgaW1hZ2VzLAogICAgICAgICAgICB0ZXh0dXJlc192ZXJzaW9uOiAwLAogICAgICAgICAgICBnbHlwaHM6IEdseXBoQ2FjaGU6Om5ldygpLAogICAgICAgICAgICBkbGlzdCwKICAgICAgICAgICAgdHJhbnNmb3JtLAogICAgICAgICAgICBwaXBlbGluZSwKICAgICAgICAgICAgdmVydGV4X2J1ZmZlciwKICAgICAgICAgICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIsCiAgICAgICAgICAgIGN1cnJlbnRfdHJhbnNmb3JtLAogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBwcmVwYXJlKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBjb250ZXh0OiAmbXV0IGNyYXRlOjpjb250ZXh0OjpDb250ZXh0LAogICAgICAgIHN0YXRlOiAmY3JhdGU6OnN1Z2FybG9hZjo6c3RhdGU6OlN1Z2FyU3RhdGUsCiAgICAgICAgZ3JhcGhpY3M6ICZtdXQgR3JhcGhpY3MsCiAgICApIHsKICAgICAgICBpZiBzdGF0ZS5yaWNoX3RleHRzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHNlbGYuY29tcC5iZWdpbigpOwogICAgICAgIGxldCBsaWJyYXJ5ID0gc3RhdGUuY29tcG9zaXRvcnMuYWR2YW5jZWQuZm9udF9saWJyYXJ5KCk7CiAgICAgICAgZm9yIHJpY2hfdGV4dCBpbiAmc3RhdGUucmljaF90ZXh0cyB7CiAgICAgICAgICAgIGlmIGxldCBTb21lKHJ0KSA9IHN0YXRlLmNvbXBvc2l0b3JzLmFkdmFuY2VkLmdldF9yaWNoX3RleHQoJnJpY2hfdGV4dC5pZCkgewogICAgICAgICAgICAgICAgbGV0IHBvc2l0aW9uID0gKAogICAgICAgICAgICAgICAgICAgIHJpY2hfdGV4dC5wb3NpdGlvblswXSAqIHN0YXRlLnN0eWxlLnNjYWxlX2ZhY3RvciwKICAgICAgICAgICAgICAgICAgICByaWNoX3RleHQucG9zaXRpb25bMV0gKiBzdGF0ZS5zdHlsZS5zY2FsZV9mYWN0b3IsCiAgICAgICAgICAgICAgICApOwoKICAgICAgICAgICAgICAgIGRyYXdfbGF5b3V0KAogICAgICAgICAgICAgICAgICAgICZtdXQgc2VsZi5jb21wLAogICAgICAgICAgICAgICAgICAgICgmbXV0IHNlbGYuaW1hZ2VzLCAmbXV0IHNlbGYuZ2x5cGhzKSwKICAgICAgICAgICAgICAgICAgICAmcnQubGluZXMsCiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgICAgICAgICAgbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICAmcnQubGF5b3V0LmRpbWVuc2lvbnMsCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgc2VsZi5pbWFnZXMucHJvY2Vzc19hdGxhc2VzKGNvbnRleHQpOwogICAgICAgIHNlbGYuY29tcC5maW5pc2goJm11dCBzZWxmLmRsaXN0KTsKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBkaW1lbnNpb25zKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgICAgICByZW5kZXJfZGF0YTogJmNyYXRlOjpsYXlvdXQ6OkJ1aWxkZXJMaW5lLAogICAgKSAtPiBPcHRpb248U3VnYXJEaW1lbnNpb25zPiB7CiAgICAgICAgc2VsZi5jb21wLmJlZ2luKCk7CgogICAgICAgIGxldCBkaW1lbnNpb24gPSBmZXRjaF9kaW1lbnNpb25zKAogICAgICAgICAgICAmbXV0IHNlbGYuY29tcCwKICAgICAgICAgICAgKCZtdXQgc2VsZi5pbWFnZXMsICZtdXQgc2VsZi5nbHlwaHMpLAogICAgICAgICAgICByZW5kZXJfZGF0YSwKICAgICAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgICk7CiAgICAgICAgaWYgZGltZW5zaW9uLmhlaWdodCA+IDAuICYmIGRpbWVuc2lvbi53aWR0aCA+IDAuIHsKICAgICAgICAgICAgU29tZShkaW1lbnNpb24pCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgTm9uZQogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiByZXNldCgmbXV0IHNlbGYpIHsKICAgICAgICBzZWxmLmdseXBocyA9IEdseXBoQ2FjaGU6Om5ldygpOwogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHJlbmRlcjwncGFzcz4oCiAgICAgICAgJidwYXNzIG11dCBzZWxmLAogICAgICAgIGN0eDogJm11dCBDb250ZXh0LAogICAgICAgIHJwYXNzOiAmbXV0IHdncHU6OlJlbmRlclBhc3M8J3Bhc3M+LAogICAgKSB7CiAgICAgICAgLy8gbGV0IHN0YXJ0ID0gc3RkOjp0aW1lOjpJbnN0YW50Ojpub3coKTsKICAgICAgICAvLyBUaGVyZSdzIG5vdGhpbmcgdG8gcmVuZGVyCiAgICAgICAgaWYgc2VsZi5kbGlzdC52ZXJ0aWNlcy5pc19lbXB0eSgpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgbGV0IHF1ZXVlID0gJm11dCBjdHgucXVldWU7CgogICAgICAgIGxldCB0cmFuc2Zvcm0gPSBvcnRob2dyYXBoaWNfcHJvamVjdGlvbihjdHguc2l6ZS53aWR0aCwgY3R4LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtX2hhc19jaGFuZ2VkID0gdHJhbnNmb3JtICE9IHNlbGYuY3VycmVudF90cmFuc2Zvcm07CgogICAgICAgIGlmIHRyYW5zZm9ybV9oYXNfY2hhbmdlZCB7CiAgICAgICAgICAgIHF1ZXVlLndyaXRlX2J1ZmZlcigmc2VsZi50cmFuc2Zvcm0sIDAsIGJ5dGVtdWNrOjpieXRlc19vZigmdHJhbnNmb3JtKSk7CiAgICAgICAgICAgIHNlbGYuY3VycmVudF90cmFuc2Zvcm0gPSB0cmFuc2Zvcm07CiAgICAgICAgfQoKICAgICAgICBpZiBzZWxmLmRsaXN0LnZlcnRpY2VzLmxlbigpID4gc2VsZi5zdXBwb3J0ZWRfdmVydGV4X2J1ZmZlciB7CiAgICAgICAgICAgIHNlbGYudmVydGV4X2J1ZmZlci5kZXN0cm95KCk7CgogICAgICAgICAgICBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyID0gc2VsZi5kbGlzdC52ZXJ0aWNlcy5sZW4oKTsKICAgICAgICAgICAgc2VsZi52ZXJ0ZXhfYnVmZmVyID0gY3R4LmRldmljZS5jcmVhdGVfYnVmZmVyKCZ3Z3B1OjpCdWZmZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgICAgIGxhYmVsOiBTb21lKCJzdWdhcmxvYWY6OnJpY2hfdGV4dDo6UGlwZWxpbmUgaW5zdGFuY2VzIiksCiAgICAgICAgICAgICAgICBzaXplOiBtZW06OnNpemVfb2Y6OjxWZXJ0ZXg+KCkgYXMgdTY0CiAgICAgICAgICAgICAgICAgICAgKiBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlZFUlRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgICAgICBtYXBwZWRfYXRfY3JlYXRpb246IGZhbHNlLAogICAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIGxldCB2ZXJ0aWNlc19ieXRlczogJlt1OF0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmc2VsZi5kbGlzdC52ZXJ0aWNlcyk7CiAgICAgICAgaWYgIXZlcnRpY2VzX2J5dGVzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYudmVydGV4X2J1ZmZlciwgMCwgdmVydGljZXNfYnl0ZXMpOwogICAgICAgIH0KCiAgICAgICAgbGV0IGluZGljZXNfcmF3OiAmW3U4XSA9IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZzZWxmLmRsaXN0LmluZGljZXMpOwogICAgICAgIGxldCBpbmRpY2VzX3Jhd19zaXplID0gaW5kaWNlc19yYXcubGVuKCkgYXMgdTY0OwoKICAgICAgICBpZiBzZWxmLmluZGV4X2J1ZmZlcl9zaXplID49IGluZGljZXNfcmF3X3NpemUgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYuaW5kZXhfYnVmZmVyLCAwLCBpbmRpY2VzX3Jhdyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIuZGVzdHJveSgpOwoKICAgICAgICAgICAgbGV0IHNpemUgPSBuZXh0X2NvcHlfYnVmZmVyX3NpemUoaW5kaWNlc19yYXdfc2l6ZSk7CiAgICAgICAgICAgIGxldCBidWZmZXIgPSBjdHguZGV2aWNlLmNyZWF0ZV9idWZmZXIoJndncHU6OkJ1ZmZlckRlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6SW5kaWNlcyIpLAogICAgICAgICAgICAgICAgc2l6ZSwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OklOREVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogdHJ1ZSwKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJ1ZmZlci5zbGljZSguLikuZ2V0X21hcHBlZF9yYW5nZV9tdXQoKVsuLmluZGljZXNfcmF3LmxlbigpXQogICAgICAgICAgICAgICAgLmNvcHlfZnJvbV9zbGljZShpbmRpY2VzX3Jhdyk7CiAgICAgICAgICAgIGJ1ZmZlci51bm1hcCgpOwoKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIgPSBidWZmZXI7CiAgICAgICAgICAgIHNlbGYuaW5kZXhfYnVmZmVyX3NpemUgPSBzaXplOwogICAgICAgIH0KCiAgICAgICAgaWYgc2VsZi50ZXh0dXJlc192ZXJzaW9uICE9IHNlbGYuaW1hZ2VzLmVudHJpZXMubGVuKCkgewogICAgICAgICAgICBzZWxmLnRleHR1cmVzX3ZlcnNpb24gPSBzZWxmLmltYWdlcy5lbnRyaWVzLmxlbigpOwogICAgICAgICAgICBzZWxmLmxheW91dF9iaW5kX2dyb3VwID0KICAgICAgICAgICAgICAgIGN0eC5kZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgICAgIGxheW91dDogJnNlbGYubGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZTogd2dwdTo6QmluZGluZ1Jlc291cmNlOjpUZXh0dXJlVmlldygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICZzZWxmLmltYWdlcy50ZXh0dXJlX3ZpZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6UGlwZWxpbmUgdW5pZm9ybXMiKSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgcnBhc3Muc2V0X3BpcGVsaW5lKCZzZWxmLnBpcGVsaW5lKTsKICAgICAgICBycGFzcy5zZXRfYmluZF9ncm91cCgwLCAmc2VsZi5jb25zdGFudF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF9iaW5kX2dyb3VwKDEsICZzZWxmLmxheW91dF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF92ZXJ0ZXhfYnVmZmVyKDAsIHNlbGYudmVydGV4X2J1ZmZlci5zbGljZSguLikpOwogICAgICAgIHJwYXNzLnNldF9pbmRleF9idWZmZXIoc2VsZi5pbmRleF9idWZmZXIuc2xpY2UoLi4pLCB3Z3B1OjpJbmRleEZvcm1hdDo6VWludDMyKTsKICAgICAgICBycGFzcy5kcmF3X2luZGV4ZWQoMC4uKHNlbGYuZGxpc3QuaW5kaWNlcy5sZW4oKSBhcyB1MzIpLCAwLCAwLi4xKTsKCiAgICAgICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgICAgIC8vIHByaW50bG4hKCIgLSByaWNoX3RleHQ6OnJlbmRlcigpIGlzOiB7Oj99IiwgZHVyYXRpb24pOwogICAgfQp9CgojW2lubGluZV0KZm4gZHJhd19sYXlvdXQoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lczogJlZlYzxjcmF0ZTo6bGF5b3V0OjpCdWlsZGVyTGluZT4sCiAgICBwb3M6IChmMzIsIGYzMiksCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgIHJlY3Q6ICZTdWdhckRpbWVuc2lvbnMsCiAgICBncmFwaGljczogJm11dCBHcmFwaGljcywKKSB7CiAgICAvLyBsZXQgc3RhcnQgPSBzdGQ6OnRpbWU6Okluc3RhbnQ6Om5vdygpOwogICAgbGV0ICh4LCB5KSA9IHBvczsKICAgIGxldCAoaW1hZ2VfY2FjaGUsIGdseXBoc19jYWNoZSkgPSBjYWNoZXM7CiAgICBsZXQgZGVwdGggPSAwLjA7CiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6bmV3KCk7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udCA9IDA7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udF9zaXplID0gMC4wOwogICAgbGV0IGZvbnRfY29vcmRzOiAmW2kxNl0gPSAmWzAsIDAsIDAsIDBdOwogICAgaWYgbGV0IFNvbWUobGluZSkgPSBsaW5lcy5maXJzdCgpIHsKICAgICAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgICAgICBjdXJyZW50X2ZvbnQgPSBmaXJzdF9ydW4uc3Bhbi5mb250X2lkOwogICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IGZpcnN0X3J1bi5zaXplOwogICAgICAgIH0KICAgIH0KCiAgICBnbHlwaHNfY2FjaGUuc2V0X21heF9oZWlnaHQocmVjdC5oZWlnaHQgYXMgdTE2KTsKCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGxhc3RfcmVuZGVyZWRfZ3JhcGhpYyA9IEhhc2hTZXQ6Om5ldygpOwogICAgbGV0IG11dCBsaW5lX3kgPSAwLiArIHk7CiAgICBmb3IgbGluZSBpbiBsaW5lcyB7CiAgICAgICAgaWYgbGluZS5yZW5kZXJfZGF0YS5ydW5zLmlzX2VtcHR5KCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIGxldCBmaXJzdF9ydW4gPSAmbGluZS5yZW5kZXJfZGF0YS5ydW5zWzBdOwogICAgICAgIC8vIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICAgICAgLy8gbGV0IGRlc2NlbnQgPSBmaXJzdF9ydW4uZGVzY2VudC5yb3VuZCgpOwogICAgICAgIC8vIGxldCBsZWFkaW5nID0gKGZpcnN0X3J1bi5sZWFkaW5nKS5yb3VuZCgpICogMi47CiAgICAgICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICAgICAgLy8gbGV0IGJhc2VsaW5lID0gbGluZV95ICsgYXNjZW50OwogICAgICAgIC8vIGxpbmVfeSA9IGJhc2VsaW5lICsgZGVzY2VudDsKICAgICAgICBsaW5lX3kgPSBsaW5lX3kgKyByZWN0LmhlaWdodDsKICAgICAgICBsZXQgcHkgPSBsaW5lX3k7CiAgICAgICAgLy8gbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICAgICAgbGV0IGxpbmVfaGVpZ2h0ID0gcmVjdC5oZWlnaHQ7CiAgICAgICAgZm9yIHJ1biBpbiAmbGluZS5yZW5kZXJfZGF0YS5ydW5zIHsKICAgICAgICAgICAgZ2x5cGhzLmNsZWFyKCk7CiAgICAgICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICAgICAgbGV0IGNoYXJfd2lkdGggPSBydW4uc3Bhbi53aWR0aDsKCiAgICAgICAgICAgIGxldCBydW5feCA9IHB4OwogICAgICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAgICAgbGV0IHggPSBweDsKICAgICAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgICAgICBweCArPSByZWN0LndpZHRoICogY2hhcl93aWR0aDsKICAgICAgICAgICAgICAgIGdseXBocy5wdXNoKEdseXBoIHsKICAgICAgICAgICAgICAgICAgICBpZDogZ2x5cGguc2ltcGxlX2RhdGEoKS4wLAogICAgICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICAgICAgeSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGZvbnRfc2l6ZTogcnVuLnNpemUsCiAgICAgICAgICAgICAgICBjb2xvcjogcnVuLnNwYW4uY29sb3IsCiAgICAgICAgICAgICAgICBjdXJzb3I6IHJ1bi5zcGFuLmN1cnNvciwKICAgICAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IHJ1bi5zcGFuLmJhY2tncm91bmRfY29sb3IsCiAgICAgICAgICAgICAgICBiYXNlbGluZTogcHksCiAgICAgICAgICAgICAgICB0b3BsaW5lOiBweSAtIHJlY3QuaGVpZ2h0LAogICAgICAgICAgICAgICAgbGluZV9oZWlnaHQsCiAgICAgICAgICAgICAgICBhZHZhbmNlOiBweCAtIHJ1bl94LAogICAgICAgICAgICAgICAgZGVjb3JhdGlvbjogcnVuLnNwYW4uZGVjb3JhdGlvbiwKICAgICAgICAgICAgICAgIGRlY29yYXRpb25fY29sb3I6IHJ1bi5zcGFuLmRlY29yYXRpb25fY29sb3IsCiAgICAgICAgICAgIH07CgogICAgICAgICAgICBpZiBmb250ICE9IGN1cnJlbnRfZm9udCB8fCBzdHlsZS5mb250X3NpemUgIT0gY3VycmVudF9mb250X3NpemUgewogICAgICAgICAgICAgICAgY3VycmVudF9mb250ID0gZm9udDsKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplID0gc3R5bGUuZm9udF9zaXplOwoKICAgICAgICAgICAgICAgIHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICAgICAgICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgICAgICAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgICAgICAgICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgICAgICAgICAgICAgIHN0eWxlLmZvbnRfc2l6ZSwKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIGlmIGxldCBTb21lKGdyYXBoaWMpID0gcnVuLnNwYW4ubWVkaWEgewogICAgICAgICAgICAgICAgaWYgIWxhc3RfcmVuZGVyZWRfZ3JhcGhpYy5jb250YWlucygmZ3JhcGhpYy5pZCkgewogICAgICAgICAgICAgICAgICAgIGxldCBvZmZzZXRfeCA9IGdyYXBoaWMub2Zmc2V0X3ggYXMgZjMyOwogICAgICAgICAgICAgICAgICAgIGxldCBvZmZzZXRfeSA9IGdyYXBoaWMub2Zmc2V0X3kgYXMgZjMyOwoKICAgICAgICAgICAgICAgICAgICBncmFwaGljcy50b3BfbGF5ZXIucHVzaChHcmFwaGljUmVuZGVyUmVxdWVzdCB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBncmFwaGljLmlkLAogICAgICAgICAgICAgICAgICAgICAgICBwb3NfeDogcnVuX3ggLSBvZmZzZXRfeCwKICAgICAgICAgICAgICAgICAgICAgICAgcG9zX3k6IHN0eWxlLnRvcGxpbmUgLSBvZmZzZXRfeSwKICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogTm9uZSwKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgICAgICBsYXN0X3JlbmRlcmVkX2dyYXBoaWMuaW5zZXJ0KGdyYXBoaWMuaWQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgICAgICBjb21wLmRyYXdfcnVuKAogICAgICAgICAgICAgICAgJm11dCBzZXNzaW9uLAogICAgICAgICAgICAgICAgUmVjdDo6bmV3KHJ1bl94LCBweSwgc3R5bGUuYWR2YW5jZSwgMS4pLAogICAgICAgICAgICAgICAgZGVwdGgsCiAgICAgICAgICAgICAgICAmc3R5bGUsCiAgICAgICAgICAgICAgICAmZ2x5cGhzLAogICAgICAgICAgICApOwogICAgICAgIH0KICAgIH0KCiAgICAvLyBsZXQgZHVyYXRpb24gPSBzdGFydC5lbGFwc2VkKCk7CiAgICAvLyBwcmludGxuISgiIC0gZHJhd19sYXlvdXQoKSBpczogezo/fVxuIiwgZHVyYXRpb24pOwp9CgojW2lubGluZV0KZm4gZmV0Y2hfZGltZW5zaW9ucygKICAgIGNvbXA6ICZtdXQgY29tcG9zaXRvcjo6Q29tcG9zaXRvciwKICAgIGNhY2hlczogKCZtdXQgSW1hZ2VDYWNoZSwgJm11dCBHbHlwaENhY2hlKSwKICAgIGxpbmU6ICZjcmF0ZTo6bGF5b3V0OjpCdWlsZGVyTGluZSwKICAgIGZvbnRfbGlicmFyeTogJkZvbnRMaWJyYXJ5LAopIC0+IFN1Z2FyRGltZW5zaW9ucyB7CiAgICBsZXQgeCA9IDAuOwogICAgbGV0IHkgPSAwLjsKCiAgICBsZXQgKGltYWdlX2NhY2hlLCBnbHlwaHNfY2FjaGUpID0gY2FjaGVzOwogICAgbGV0IG11dCBjdXJyZW50X2ZvbnQgPSAwOwogICAgbGV0IG11dCBjdXJyZW50X2ZvbnRfc2l6ZSA9IDAuMDsKICAgIGxldCBmb250X2Nvb3JkczogJltpMTZdID0gJlswLCAwLCAwLCAwXTsKICAgIGlmIGxldCBTb21lKGZpcnN0X3J1bikgPSBsaW5lLnJlbmRlcl9kYXRhLnJ1bnMuZmlyc3QoKSB7CiAgICAgICAgY3VycmVudF9mb250ID0gZmlyc3RfcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IGZpcnN0X3J1bi5zaXplOwogICAgfQoKICAgIGxldCBtdXQgc2Vzc2lvbiA9IGdseXBoc19jYWNoZS5zZXNzaW9uKAogICAgICAgIGltYWdlX2NhY2hlLAogICAgICAgIGN1cnJlbnRfZm9udCwKICAgICAgICBmb250X2xpYnJhcnksCiAgICAgICAgZm9udF9jb29yZHMsCiAgICAgICAgY3VycmVudF9mb250X3NpemUsCiAgICApOwoKICAgIGxldCBtdXQgZ2x5cGhzID0gVmVjOjp3aXRoX2NhcGFjaXR5KDMpOwogICAgbGV0IG11dCBkaW1lbnNpb24gPSBTdWdhckRpbWVuc2lvbnM6OmRlZmF1bHQoKTsKICAgIGxldCBmaXJzdF9ydW4gPSAmbGluZS5yZW5kZXJfZGF0YS5ydW5zWzBdOwogICAgbGV0IGFzY2VudCA9IGZpcnN0X3J1bi5hc2NlbnQucm91bmQoKTsKICAgIGxldCBkZXNjZW50ID0gZmlyc3RfcnVuLmRlc2NlbnQucm91bmQoKTsKICAgIGxldCBsZWFkaW5nID0gKGZpcnN0X3J1bi5sZWFkaW5nKS5yb3VuZCgpICogMi47CiAgICAvLyBsZXQgbXV0IHB4ID0geCArIGxpbmUub2Zmc2V0KCk7CiAgICBsZXQgbXV0IHB4ID0geCArIDAuMDsKICAgIGxldCBweSA9IGFzY2VudCArIHk7CiAgICBsZXQgbGluZV9oZWlnaHQgPSBhc2NlbnQgKyBkZXNjZW50ICsgbGVhZGluZzsKICAgIGZvciBydW4gaW4gJmxpbmUucmVuZGVyX2RhdGEucnVucyB7CiAgICAgICAgbGV0IGNoYXJfd2lkdGggPSBydW4uc3Bhbi53aWR0aDsKCiAgICAgICAgbGV0IGZvbnQgPSBydW4uc3Bhbi5mb250X2lkOwogICAgICAgIGxldCBydW5feCA9IHB4OwogICAgICAgIGdseXBocy5jbGVhcigpOwogICAgICAgIGZvciBnbHlwaCBpbiAmcnVuLmdseXBocyB7CiAgICAgICAgICAgIC8vIGxldCB4ID0gcHggKyBnbHlwaC54OwogICAgICAgICAgICAvLyBsZXQgeSA9IHB5IC0gZ2x5cGgueTsKICAgICAgICAgICAgbGV0IHggPSBweDsKICAgICAgICAgICAgbGV0IHkgPSBweTsKICAgICAgICAgICAgLy8gcHggKz0gZ2x5cGguYWR2YW5jZQogICAgICAgICAgICBweCArPSBnbHlwaC5zaW1wbGVfZGF0YSgpLjEgKiBjaGFyX3dpZHRoOwogICAgICAgICAgICBnbHlwaHMucHVzaChHbHlwaCB7CiAgICAgICAgICAgICAgICBpZDogZ2x5cGguc2ltcGxlX2RhdGEoKS4wLAogICAgICAgICAgICAgICAgeCwKICAgICAgICAgICAgICAgIHksCiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgICBsZXQgY29sb3IgPSBydW4uc3Bhbi5jb2xvcjsKCiAgICAgICAgbGV0IHN0eWxlID0gVGV4dFJ1blN0eWxlIHsKICAgICAgICAgICAgZm9udF9jb29yZHMsCiAgICAgICAgICAgIGZvbnRfc2l6ZTogcnVuLnNpemUsCiAgICAgICAgICAgIGNvbG9yLAogICAgICAgICAgICBjdXJzb3I6IHJ1bi5zcGFuLmN1cnNvciwKICAgICAgICAgICAgYmFja2dyb3VuZF9jb2xvcjogTm9uZSwKICAgICAgICAgICAgYmFzZWxpbmU6IHB5LAogICAgICAgICAgICB0b3BsaW5lOiBweSAtIGFzY2VudCwKICAgICAgICAgICAgbGluZV9oZWlnaHQsCiAgICAgICAgICAgIGFkdmFuY2U6IHB4IC0gcnVuX3gsCiAgICAgICAgICAgIGRlY29yYXRpb246IE5vbmUsCiAgICAgICAgICAgIGRlY29yYXRpb25fY29sb3I6IE5vbmUsCiAgICAgICAgfTsKCiAgICAgICAgaWYgc3R5bGUuYWR2YW5jZSA+IDAuICYmIGxpbmVfaGVpZ2h0ID4gMC4gewogICAgICAgICAgICBkaW1lbnNpb24ud2lkdGggPSBzdHlsZS5hZHZhbmNlLnJvdW5kKCk7CiAgICAgICAgICAgIGRpbWVuc2lvbi5oZWlnaHQgPSBsaW5lX2hlaWdodC5yb3VuZCgpOwogICAgICAgIH0KCiAgICAgICAgaWYgZm9udCAhPSBjdXJyZW50X2ZvbnQgfHwgc3R5bGUuZm9udF9zaXplICE9IGN1cnJlbnRfZm9udF9zaXplIHsKICAgICAgICAgICAgY3VycmVudF9mb250ID0gZm9udDsKICAgICAgICAgICAgY3VycmVudF9mb250X3NpemUgPSBzdHlsZS5mb250X3NpemU7CgogICAgICAgICAgICBzZXNzaW9uID0gZ2x5cGhzX2NhY2hlLnNlc3Npb24oCiAgICAgICAgICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udCwKICAgICAgICAgICAgICAgIGZvbnRfbGlicmFyeSwKICAgICAgICAgICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgICAgICAgICAgY3VycmVudF9mb250X3NpemUsCiAgICAgICAgICAgICk7CiAgICAgICAgfQoKICAgICAgICBjb21wLmRyYXdfcnVuKAogICAgICAgICAgICAmbXV0IHNlc3Npb24sCiAgICAgICAgICAgIFJlY3Q6Om5ldyhydW5feCwgcHksIHN0eWxlLmFkdmFuY2UsIDEuKSwKICAgICAgICAgICAgMC4wLAogICAgICAgICAgICAmc3R5bGUsCiAgICAgICAgICAgICZnbHlwaHMsCiAgICAgICAgKTsKICAgIH0KCiAgICBkaW1lbnNpb24KfQoKI1tpbmxpbmVdCmZuIG5leHRfY29weV9idWZmZXJfc2l6ZShzaXplOiB1NjQpIC0+IHU2NCB7CiAgICBsZXQgYWxpZ25fbWFzayA9IHdncHU6OkNPUFlfQlVGRkVSX0FMSUdOTUVOVCAtIDE7CiAgICAoKHNpemUubmV4dF9wb3dlcl9vZl90d28oKSArIGFsaWduX21hc2spICYgIWFsaWduX21hc2spCiAgICAgICAgLm1heCh3Z3B1OjpDT1BZX0JVRkZFUl9BTElHTk1FTlQpCn0KAAAAAAAAAABTVgAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACZPwAAAAAAAJk/AAAAAAAAAAAAAAAA8L8" - ], - [ - 125, - 1, - "revert", - null, - "AgAAAAAAAAAAAAAAAAAAAAAAAABTVgAAbW9kIGJhdGNoOwptb2QgY29tcG9zaXRvcjsKbW9kIGltYWdlX2NhY2hlOwpwdWIgbW9kIHRleHQ7Cgp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OmNvcmU6Om9ydGhvZ3JhcGhpY19wcm9qZWN0aW9uOwp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OnJpY2hfdGV4dDo6aW1hZ2VfY2FjaGU6OntHbHlwaENhY2hlLCBJbWFnZUNhY2hlfTsKdXNlIGNyYXRlOjpjb250ZXh0OjpDb250ZXh0Owp1c2UgY3JhdGU6OmZvbnQ6OkZvbnRMaWJyYXJ5Owp1c2UgY3JhdGU6OmxheW91dDo6U3VnYXJEaW1lbnNpb25zOwp1c2UgY3JhdGU6OnN1Z2FybG9hZjo6Z3JhcGhpY3M6OkdyYXBoaWNSZW5kZXJSZXF1ZXN0Owp1c2UgY3JhdGU6OkdyYXBoaWNzOwp1c2UgY29tcG9zaXRvcjo6e0NvbXBvc2l0b3IsIERpc3BsYXlMaXN0LCBSZWN0LCBWZXJ0ZXh9Owp1c2Ugc3RkOjpjb2xsZWN0aW9uczo6SGFzaFNldDsKdXNlIHN0ZDo6e2JvcnJvdzo6Q293LCBtZW19Owp1c2UgdGV4dDo6e0dseXBoLCBUZXh0UnVuU3R5bGV9Owp1c2Ugd2dwdTo6dXRpbDo6RGV2aWNlRXh0OwoKLy8gTm90ZTogY3VycmVudGx5IGl0J3MgdXNpbmcgSW5kZXhlZCBkcmF3aW5nIGluc3RlYWQgb2YgSW5zdGFuY2UgZHJhd2luZyBjb3VsZCBiZSB3b3J0aCB0bwovLyBldmFsdWF0ZSBpZiB3b3VsZCBtYWtlIHNlbnNlIG1vdmUgdG8gaW5zdGFuY2UgZHJhd2luZyBpbnN0ZWFkCi8vIGh0dHBzOi8vbWF0aC5od3MuZWR1L2dyYXBoaWNzYm9vay9jOS9zMi5odG1sCi8vIGh0dHBzOi8vZG9jcy5ycy93Z3B1L2xhdGVzdC93Z3B1L2VudW0uVmVydGV4U3RlcE1vZGUuaHRtbAoKcHViIGNvbnN0IEJMRU5EOiBPcHRpb248d2dwdTo6QmxlbmRTdGF0ZT4gPSBTb21lKHdncHU6OkJsZW5kU3RhdGUgewogICAgY29sb3I6IHdncHU6OkJsZW5kQ29tcG9uZW50IHsKICAgICAgICBzcmNfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6U3JjQWxwaGEsCiAgICAgICAgZHN0X2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZU1pbnVzU3JjQWxwaGEsCiAgICAgICAgb3BlcmF0aW9uOiB3Z3B1OjpCbGVuZE9wZXJhdGlvbjo6QWRkLAogICAgfSwKICAgIGFscGhhOiB3Z3B1OjpCbGVuZENvbXBvbmVudCB7CiAgICAgICAgc3JjX2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZSwKICAgICAgICBkc3RfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6T25lTWludXNTcmNBbHBoYSwKICAgICAgICBvcGVyYXRpb246IHdncHU6OkJsZW5kT3BlcmF0aW9uOjpBZGQsCiAgICB9LAp9KTsKCnB1YiBzdHJ1Y3QgUmljaFRleHRCcnVzaCB7CiAgICB2ZXJ0ZXhfYnVmZmVyOiB3Z3B1OjpCdWZmZXIsCiAgICBjb25zdGFudF9iaW5kX2dyb3VwOiB3Z3B1OjpCaW5kR3JvdXAsCiAgICBsYXlvdXRfYmluZF9ncm91cDogd2dwdTo6QmluZEdyb3VwLAogICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0OiB3Z3B1OjpCaW5kR3JvdXBMYXlvdXQsCiAgICB0cmFuc2Zvcm06IHdncHU6OkJ1ZmZlciwKICAgIHBpcGVsaW5lOiB3Z3B1OjpSZW5kZXJQaXBlbGluZSwKICAgIGluZGV4X2J1ZmZlcjogd2dwdTo6QnVmZmVyLAogICAgaW5kZXhfYnVmZmVyX3NpemU6IHU2NCwKICAgIGN1cnJlbnRfdHJhbnNmb3JtOiBbZjMyOyAxNl0sCiAgICBjb21wOiBDb21wb3NpdG9yLAogICAgZGxpc3Q6IERpc3BsYXlMaXN0LAogICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXI6IHVzaXplLAogICAgdGV4dHVyZXNfdmVyc2lvbjogdXNpemUsCiAgICBpbWFnZXM6IEltYWdlQ2FjaGUsCiAgICBnbHlwaHM6IEdseXBoQ2FjaGUsCn0KCmltcGwgUmljaFRleHRCcnVzaCB7CiAgICBwdWIgZm4gbmV3KGNvbnRleHQ6ICZDb250ZXh0KSAtPiBTZWxmIHsKICAgICAgICBsZXQgZGV2aWNlID0gJmNvbnRleHQuZGV2aWNlOwogICAgICAgIGxldCBkbGlzdCA9IERpc3BsYXlMaXN0OjpuZXcoKTsKICAgICAgICBsZXQgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIgPSAyXzAwMDsKCiAgICAgICAgbGV0IGN1cnJlbnRfdHJhbnNmb3JtID0KICAgICAgICAgICAgb3J0aG9ncmFwaGljX3Byb2plY3Rpb24oY29udGV4dC5zaXplLndpZHRoLCBjb250ZXh0LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtID0gZGV2aWNlLmNyZWF0ZV9idWZmZXJfaW5pdCgmd2dwdTo6dXRpbDo6QnVmZmVySW5pdERlc2NyaXB0b3IgewogICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgY29udGVudHM6IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZjdXJyZW50X3RyYW5zZm9ybSksCiAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlVOSUZPUk0gfCB3Z3B1OjpCdWZmZXJVc2FnZXM6OkNPUFlfRFNULAogICAgICAgIH0pOwoKICAgICAgICAvLyBDcmVhdGUgcGlwZWxpbmUgbGF5b3V0CiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9iaW5kX2dyb3VwX2xheW91dCgmd2dwdTo6QmluZEdyb3VwTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbCiAgICAgICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwTGF5b3V0RW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmlsaXR5OiB3Z3B1OjpTaGFkZXJTdGFnZXM6OlZFUlRFWCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpCdWZmZXIgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJ1ZmZlckJpbmRpbmdUeXBlOjpVbmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzX2R5bmFtaWNfb2Zmc2V0OiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9iaW5kaW5nX3NpemU6IHdncHU6OkJ1ZmZlclNpemU6Om5ldyhtZW06OnNpemVfb2Y6OjwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZjMyOyAxNl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzIHdncHU6OkJ1ZmZlckFkZHJlc3MpLAogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogTm9uZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgYmluZGluZzogMSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogd2dwdTo6U2hhZGVyU3RhZ2VzOjpWRVJURVgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgd2dwdTo6U2hhZGVyU3RhZ2VzOjpGUkFHTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpTYW1wbGVyKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2dwdTo6U2FtcGxlckJpbmRpbmdUeXBlOjpGaWx0ZXJpbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGxheW91dF9iaW5kX2dyb3VwX2xheW91dCA9CiAgICAgICAgICAgIGRldmljZS5jcmVhdGVfYmluZF9ncm91cF9sYXlvdXQoJndncHU6OkJpbmRHcm91cExheW91dERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgICAgICBlbnRyaWVzOiAmW3dncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6IHdncHU6OlNoYWRlclN0YWdlczo6RlJBR01FTlQsCiAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpUZXh0dXJlIHsKICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX3R5cGU6IHdncHU6OlRleHR1cmVTYW1wbGVUeXBlOjpGbG9hdCB7IGZpbHRlcmFibGU6IHRydWUgfSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlld19kaW1lbnNpb246IHdncHU6OlRleHR1cmVWaWV3RGltZW5zaW9uOjpEMiwKICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlzYW1wbGVkOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgIH0pOwoKICAgICAgICBsZXQgcGlwZWxpbmVfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9waXBlbGluZV9sYXlvdXQoJndncHU6OlBpcGVsaW5lTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIHB1c2hfY29uc3RhbnRfcmFuZ2VzOiAmW10sCiAgICAgICAgICAgICAgICBiaW5kX2dyb3VwX2xheW91dHM6ICZbCiAgICAgICAgICAgICAgICAgICAgJmNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgICZsYXlvdXRfYmluZF9ncm91cF9sYXlvdXQsCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGltYWdlcyA9IEltYWdlQ2FjaGU6Om5ldyhjb250ZXh0KTsKCiAgICAgICAgbGV0IHNhbXBsZXIgPSBkZXZpY2UuY3JlYXRlX3NhbXBsZXIoJndncHU6OlNhbXBsZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3U6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3Y6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3c6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgbWFnX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWluX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWlwbWFwX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbG9kX21pbl9jbGFtcDogMGYzMiwKICAgICAgICAgICAgbG9kX21heF9jbGFtcDogMGYzMiwKICAgICAgICAgICAgLi5EZWZhdWx0OjpkZWZhdWx0KCkKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXAgPSBkZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICBsYXlvdXQ6ICZjb25zdGFudF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlsKICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHJlc291cmNlOiB3Z3B1OjpCaW5kaW5nUmVzb3VyY2U6OkJ1ZmZlcih3Z3B1OjpCdWZmZXJCaW5kaW5nIHsKICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiAmdHJhbnNmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgIGJpbmRpbmc6IDEsCiAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6U2FtcGxlcigmc2FtcGxlciksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICBdLAogICAgICAgICAgICBsYWJlbDogU29tZSgicmljaF90ZXh0Ojpjb25zdGFudF9iaW5kX2dyb3VwIiksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBsYXlvdXRfYmluZF9ncm91cCA9IGRldmljZS5jcmVhdGVfYmluZF9ncm91cCgmd2dwdTo6QmluZEdyb3VwRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxheW91dDogJmxheW91dF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlt3Z3B1OjpCaW5kR3JvdXBFbnRyeSB7CiAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6VGV4dHVyZVZpZXcoJmltYWdlcy50ZXh0dXJlX3ZpZXcpLAogICAgICAgICAgICB9XSwKICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6bGF5b3V0X2JpbmRfZ3JvdXAiKSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHNoYWRlciA9IGRldmljZS5jcmVhdGVfc2hhZGVyX21vZHVsZSh3Z3B1OjpTaGFkZXJNb2R1bGVEZXNjcmlwdG9yIHsKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIHNvdXJjZTogd2dwdTo6U2hhZGVyU291cmNlOjpXZ3NsKENvdzo6Qm9ycm93ZWQoaW5jbHVkZV9zdHIhKAogICAgICAgICAgICAgICAgInJpY2hfdGV4dC53Z3NsIgogICAgICAgICAgICApKSksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBwaXBlbGluZSA9IGRldmljZS5jcmVhdGVfcmVuZGVyX3BpcGVsaW5lKCZ3Z3B1OjpSZW5kZXJQaXBlbGluZURlc2NyaXB0b3IgewogICAgICAgICAgICBjYWNoZTogTm9uZSwKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIGxheW91dDogU29tZSgmcGlwZWxpbmVfbGF5b3V0KSwKICAgICAgICAgICAgdmVydGV4OiB3Z3B1OjpWZXJ0ZXhTdGF0ZSB7CiAgICAgICAgICAgICAgICBjb21waWxhdGlvbl9vcHRpb25zOiB3Z3B1OjpQaXBlbGluZUNvbXBpbGF0aW9uT3B0aW9uczo6ZGVmYXVsdCgpLAogICAgICAgICAgICAgICAgbW9kdWxlOiAmc2hhZGVyLAogICAgICAgICAgICAgICAgZW50cnlfcG9pbnQ6IFNvbWUoInZzX21haW4iKSwKICAgICAgICAgICAgICAgIGJ1ZmZlcnM6ICZbd2dwdTo6VmVydGV4QnVmZmVyTGF5b3V0IHsKICAgICAgICAgICAgICAgICAgICBhcnJheV9zdHJpZGU6IG1lbTo6c2l6ZV9vZjo6PFZlcnRleD4oKSBhcyB1NjQsCiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLnJzL3dncHUvbGF0ZXN0L3dncHUvZW51bS5WZXJ0ZXhTdGVwTW9kZS5odG1sCiAgICAgICAgICAgICAgICAgICAgc3RlcF9tb2RlOiB3Z3B1OjpWZXJ0ZXhTdGVwTW9kZTo6VmVydGV4LAogICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6ICZ3Z3B1Ojp2ZXJ0ZXhfYXR0cl9hcnJheSEoCiAgICAgICAgICAgICAgICAgICAgICAgIDAgPT4gRmxvYXQzMngzLAogICAgICAgICAgICAgICAgICAgICAgICAxID0+IEZsb2F0MzJ4NCwKICAgICAgICAgICAgICAgICAgICAgICAgMiA9PiBGbG9hdDMyeDIsCiAgICAgICAgICAgICAgICAgICAgICAgIDMgPT4gU2ludDMyeDIsCiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIH1dLAogICAgICAgICAgICB9LAogICAgICAgICAgICBmcmFnbWVudDogU29tZSh3Z3B1OjpGcmFnbWVudFN0YXRlIHsKICAgICAgICAgICAgICAgIGNvbXBpbGF0aW9uX29wdGlvbnM6IHdncHU6OlBpcGVsaW5lQ29tcGlsYXRpb25PcHRpb25zOjpkZWZhdWx0KCksCiAgICAgICAgICAgICAgICBtb2R1bGU6ICZzaGFkZXIsCiAgICAgICAgICAgICAgICBlbnRyeV9wb2ludDogU29tZSgiZnNfbWFpbiIpLAogICAgICAgICAgICAgICAgdGFyZ2V0czogJltTb21lKHdncHU6OkNvbG9yVGFyZ2V0U3RhdGUgewogICAgICAgICAgICAgICAgICAgIGZvcm1hdDogY29udGV4dC5mb3JtYXQsCiAgICAgICAgICAgICAgICAgICAgYmxlbmQ6IEJMRU5ELAogICAgICAgICAgICAgICAgICAgIHdyaXRlX21hc2s6IHdncHU6OkNvbG9yV3JpdGVzOjpBTEwsCiAgICAgICAgICAgICAgICB9KV0sCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICBwcmltaXRpdmU6IHdncHU6OlByaW1pdGl2ZVN0YXRlIHsKICAgICAgICAgICAgICAgIHRvcG9sb2d5OiB3Z3B1OjpQcmltaXRpdmVUb3BvbG9neTo6VHJpYW5nbGVMaXN0LAogICAgICAgICAgICAgICAgc3RyaXBfaW5kZXhfZm9ybWF0OiBOb25lLAogICAgICAgICAgICAgICAgZnJvbnRfZmFjZTogd2dwdTo6RnJvbnRGYWNlOjpDY3csCiAgICAgICAgICAgICAgICBjdWxsX21vZGU6IE5vbmUsCiAgICAgICAgICAgICAgICBwb2x5Z29uX21vZGU6IHdncHU6OlBvbHlnb25Nb2RlOjpGaWxsLAogICAgICAgICAgICAgICAgdW5jbGlwcGVkX2RlcHRoOiBmYWxzZSwKICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZTogZmFsc2UsCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGRlcHRoX3N0ZW5jaWw6IE5vbmUsCiAgICAgICAgICAgIG11bHRpc2FtcGxlOiB3Z3B1OjpNdWx0aXNhbXBsZVN0YXRlOjpkZWZhdWx0KCksCiAgICAgICAgICAgIG11bHRpdmlldzogTm9uZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHZlcnRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6Okluc3RhbmNlcyBCdWZmZXIiKSwKICAgICAgICAgICAgc2l6ZTogbWVtOjpzaXplX29mOjo8VmVydGV4PigpIGFzIHU2NCAqIHN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgdXNhZ2U6IHdncHU6OkJ1ZmZlclVzYWdlczo6VkVSVEVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgbWFwcGVkX2F0X2NyZWF0aW9uOiBmYWxzZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplOiAmW3UzMl0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmZGxpc3QuaW5kaWNlcyk7CiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplID0gaW5kZXhfYnVmZmVyX3NpemUubGVuKCkgYXMgdTY0OwogICAgICAgIGxldCBpbmRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6OkluZGljZXMgQnVmZmVyIiksCiAgICAgICAgICAgIHNpemU6IGluZGV4X2J1ZmZlcl9zaXplLAogICAgICAgICAgICB1c2FnZTogd2dwdTo6QnVmZmVyVXNhZ2VzOjpJTkRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogZmFsc2UsCiAgICAgICAgfSk7CgogICAgICAgIFJpY2hUZXh0QnJ1c2ggewogICAgICAgICAgICBsYXlvdXRfYmluZF9ncm91cCwKICAgICAgICAgICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICBjb25zdGFudF9iaW5kX2dyb3VwLAogICAgICAgICAgICBpbmRleF9idWZmZXJfc2l6ZSwKICAgICAgICAgICAgaW5kZXhfYnVmZmVyLAogICAgICAgICAgICBjb21wOiBDb21wb3NpdG9yOjpuZXcoKSwKICAgICAgICAgICAgaW1hZ2VzLAogICAgICAgICAgICB0ZXh0dXJlc192ZXJzaW9uOiAwLAogICAgICAgICAgICBnbHlwaHM6IEdseXBoQ2FjaGU6Om5ldygpLAogICAgICAgICAgICBkbGlzdCwKICAgICAgICAgICAgdHJhbnNmb3JtLAogICAgICAgICAgICBwaXBlbGluZSwKICAgICAgICAgICAgdmVydGV4X2J1ZmZlciwKICAgICAgICAgICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIsCiAgICAgICAgICAgIGN1cnJlbnRfdHJhbnNmb3JtLAogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBwcmVwYXJlKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBjb250ZXh0OiAmbXV0IGNyYXRlOjpjb250ZXh0OjpDb250ZXh0LAogICAgICAgIHN0YXRlOiAmY3JhdGU6OnN1Z2FybG9hZjo6c3RhdGU6OlN1Z2FyU3RhdGUsCiAgICAgICAgZ3JhcGhpY3M6ICZtdXQgR3JhcGhpY3MsCiAgICApIHsKICAgICAgICBpZiBzdGF0ZS5yaWNoX3RleHRzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHNlbGYuY29tcC5iZWdpbigpOwogICAgICAgIGxldCBsaWJyYXJ5ID0gc3RhdGUuY29tcG9zaXRvcnMuYWR2YW5jZWQuZm9udF9saWJyYXJ5KCk7CiAgICAgICAgZm9yIHJpY2hfdGV4dCBpbiAmc3RhdGUucmljaF90ZXh0cyB7CiAgICAgICAgICAgIGlmIGxldCBTb21lKHJ0KSA9IHN0YXRlLmNvbXBvc2l0b3JzLmFkdmFuY2VkLmdldF9yaWNoX3RleHQoJnJpY2hfdGV4dC5pZCkgewogICAgICAgICAgICAgICAgbGV0IHBvc2l0aW9uID0gKAogICAgICAgICAgICAgICAgICAgIHJpY2hfdGV4dC5wb3NpdGlvblswXSAqIHN0YXRlLnN0eWxlLnNjYWxlX2ZhY3RvciwKICAgICAgICAgICAgICAgICAgICByaWNoX3RleHQucG9zaXRpb25bMV0gKiBzdGF0ZS5zdHlsZS5zY2FsZV9mYWN0b3IsCiAgICAgICAgICAgICAgICApOwoKICAgICAgICAgICAgICAgIGRyYXdfbGF5b3V0KAogICAgICAgICAgICAgICAgICAgICZtdXQgc2VsZi5jb21wLAogICAgICAgICAgICAgICAgICAgICgmbXV0IHNlbGYuaW1hZ2VzLCAmbXV0IHNlbGYuZ2x5cGhzKSwKICAgICAgICAgICAgICAgICAgICAmcnQubGluZXMsCiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgICAgICAgICAgbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICAmcnQubGF5b3V0LmRpbWVuc2lvbnMsCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgc2VsZi5pbWFnZXMucHJvY2Vzc19hdGxhc2VzKGNvbnRleHQpOwogICAgICAgIHNlbGYuY29tcC5maW5pc2goJm11dCBzZWxmLmRsaXN0KTsKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBkaW1lbnNpb25zKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgICAgICByZW5kZXJfZGF0YTogJmNyYXRlOjpsYXlvdXQ6OkJ1aWxkZXJMaW5lLAogICAgKSAtPiBPcHRpb248U3VnYXJEaW1lbnNpb25zPiB7CiAgICAgICAgc2VsZi5jb21wLmJlZ2luKCk7CgogICAgICAgIGxldCBkaW1lbnNpb24gPSBmZXRjaF9kaW1lbnNpb25zKAogICAgICAgICAgICAmbXV0IHNlbGYuY29tcCwKICAgICAgICAgICAgKCZtdXQgc2VsZi5pbWFnZXMsICZtdXQgc2VsZi5nbHlwaHMpLAogICAgICAgICAgICByZW5kZXJfZGF0YSwKICAgICAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgICk7CiAgICAgICAgaWYgZGltZW5zaW9uLmhlaWdodCA+IDAuICYmIGRpbWVuc2lvbi53aWR0aCA+IDAuIHsKICAgICAgICAgICAgU29tZShkaW1lbnNpb24pCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgTm9uZQogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiByZXNldCgmbXV0IHNlbGYpIHsKICAgICAgICBzZWxmLmdseXBocyA9IEdseXBoQ2FjaGU6Om5ldygpOwogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHJlbmRlcjwncGFzcz4oCiAgICAgICAgJidwYXNzIG11dCBzZWxmLAogICAgICAgIGN0eDogJm11dCBDb250ZXh0LAogICAgICAgIHJwYXNzOiAmbXV0IHdncHU6OlJlbmRlclBhc3M8J3Bhc3M+LAogICAgKSB7CiAgICAgICAgLy8gbGV0IHN0YXJ0ID0gc3RkOjp0aW1lOjpJbnN0YW50Ojpub3coKTsKICAgICAgICAvLyBUaGVyZSdzIG5vdGhpbmcgdG8gcmVuZGVyCiAgICAgICAgaWYgc2VsZi5kbGlzdC52ZXJ0aWNlcy5pc19lbXB0eSgpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgbGV0IHF1ZXVlID0gJm11dCBjdHgucXVldWU7CgogICAgICAgIGxldCB0cmFuc2Zvcm0gPSBvcnRob2dyYXBoaWNfcHJvamVjdGlvbihjdHguc2l6ZS53aWR0aCwgY3R4LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtX2hhc19jaGFuZ2VkID0gdHJhbnNmb3JtICE9IHNlbGYuY3VycmVudF90cmFuc2Zvcm07CgogICAgICAgIGlmIHRyYW5zZm9ybV9oYXNfY2hhbmdlZCB7CiAgICAgICAgICAgIHF1ZXVlLndyaXRlX2J1ZmZlcigmc2VsZi50cmFuc2Zvcm0sIDAsIGJ5dGVtdWNrOjpieXRlc19vZigmdHJhbnNmb3JtKSk7CiAgICAgICAgICAgIHNlbGYuY3VycmVudF90cmFuc2Zvcm0gPSB0cmFuc2Zvcm07CiAgICAgICAgfQoKICAgICAgICBpZiBzZWxmLmRsaXN0LnZlcnRpY2VzLmxlbigpID4gc2VsZi5zdXBwb3J0ZWRfdmVydGV4X2J1ZmZlciB7CiAgICAgICAgICAgIHNlbGYudmVydGV4X2J1ZmZlci5kZXN0cm95KCk7CgogICAgICAgICAgICBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyID0gc2VsZi5kbGlzdC52ZXJ0aWNlcy5sZW4oKTsKICAgICAgICAgICAgc2VsZi52ZXJ0ZXhfYnVmZmVyID0gY3R4LmRldmljZS5jcmVhdGVfYnVmZmVyKCZ3Z3B1OjpCdWZmZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgICAgIGxhYmVsOiBTb21lKCJzdWdhcmxvYWY6OnJpY2hfdGV4dDo6UGlwZWxpbmUgaW5zdGFuY2VzIiksCiAgICAgICAgICAgICAgICBzaXplOiBtZW06OnNpemVfb2Y6OjxWZXJ0ZXg+KCkgYXMgdTY0CiAgICAgICAgICAgICAgICAgICAgKiBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlZFUlRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgICAgICBtYXBwZWRfYXRfY3JlYXRpb246IGZhbHNlLAogICAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIGxldCB2ZXJ0aWNlc19ieXRlczogJlt1OF0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmc2VsZi5kbGlzdC52ZXJ0aWNlcyk7CiAgICAgICAgaWYgIXZlcnRpY2VzX2J5dGVzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYudmVydGV4X2J1ZmZlciwgMCwgdmVydGljZXNfYnl0ZXMpOwogICAgICAgIH0KCiAgICAgICAgbGV0IGluZGljZXNfcmF3OiAmW3U4XSA9IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZzZWxmLmRsaXN0LmluZGljZXMpOwogICAgICAgIGxldCBpbmRpY2VzX3Jhd19zaXplID0gaW5kaWNlc19yYXcubGVuKCkgYXMgdTY0OwoKICAgICAgICBpZiBzZWxmLmluZGV4X2J1ZmZlcl9zaXplID49IGluZGljZXNfcmF3X3NpemUgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYuaW5kZXhfYnVmZmVyLCAwLCBpbmRpY2VzX3Jhdyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIuZGVzdHJveSgpOwoKICAgICAgICAgICAgbGV0IHNpemUgPSBuZXh0X2NvcHlfYnVmZmVyX3NpemUoaW5kaWNlc19yYXdfc2l6ZSk7CiAgICAgICAgICAgIGxldCBidWZmZXIgPSBjdHguZGV2aWNlLmNyZWF0ZV9idWZmZXIoJndncHU6OkJ1ZmZlckRlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6SW5kaWNlcyIpLAogICAgICAgICAgICAgICAgc2l6ZSwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OklOREVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogdHJ1ZSwKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJ1ZmZlci5zbGljZSguLikuZ2V0X21hcHBlZF9yYW5nZV9tdXQoKVsuLmluZGljZXNfcmF3LmxlbigpXQogICAgICAgICAgICAgICAgLmNvcHlfZnJvbV9zbGljZShpbmRpY2VzX3Jhdyk7CiAgICAgICAgICAgIGJ1ZmZlci51bm1hcCgpOwoKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIgPSBidWZmZXI7CiAgICAgICAgICAgIHNlbGYuaW5kZXhfYnVmZmVyX3NpemUgPSBzaXplOwogICAgICAgIH0KCiAgICAgICAgaWYgc2VsZi50ZXh0dXJlc192ZXJzaW9uICE9IHNlbGYuaW1hZ2VzLmVudHJpZXMubGVuKCkgewogICAgICAgICAgICBzZWxmLnRleHR1cmVzX3ZlcnNpb24gPSBzZWxmLmltYWdlcy5lbnRyaWVzLmxlbigpOwogICAgICAgICAgICBzZWxmLmxheW91dF9iaW5kX2dyb3VwID0KICAgICAgICAgICAgICAgIGN0eC5kZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgICAgIGxheW91dDogJnNlbGYubGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZTogd2dwdTo6QmluZGluZ1Jlc291cmNlOjpUZXh0dXJlVmlldygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICZzZWxmLmltYWdlcy50ZXh0dXJlX3ZpZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6UGlwZWxpbmUgdW5pZm9ybXMiKSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgcnBhc3Muc2V0X3BpcGVsaW5lKCZzZWxmLnBpcGVsaW5lKTsKICAgICAgICBycGFzcy5zZXRfYmluZF9ncm91cCgwLCAmc2VsZi5jb25zdGFudF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF9iaW5kX2dyb3VwKDEsICZzZWxmLmxheW91dF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF92ZXJ0ZXhfYnVmZmVyKDAsIHNlbGYudmVydGV4X2J1ZmZlci5zbGljZSguLikpOwogICAgICAgIHJwYXNzLnNldF9pbmRleF9idWZmZXIoc2VsZi5pbmRleF9idWZmZXIuc2xpY2UoLi4pLCB3Z3B1OjpJbmRleEZvcm1hdDo6VWludDMyKTsKICAgICAgICBycGFzcy5kcmF3X2luZGV4ZWQoMC4uKHNlbGYuZGxpc3QuaW5kaWNlcy5sZW4oKSBhcyB1MzIpLCAwLCAwLi4xKTsKCiAgICAgICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgICAgIC8vIHByaW50bG4hKCIgLSByaWNoX3RleHQ6OnJlbmRlcigpIGlzOiB7Oj99IiwgZHVyYXRpb24pOwogICAgfQp9CgojW2lubGluZV0KZm4gZHJhd19sYXlvdXQoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lczogJlZlYzxjcmF0ZTo6bGF5b3V0OjpCdWlsZGVyTGluZT4sCiAgICBwb3M6IChmMzIsIGYzMiksCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgIHJlY3Q6ICZTdWdhckRpbWVuc2lvbnMsCiAgICBncmFwaGljczogJm11dCBHcmFwaGljcywKKSB7CiAgICAvLyBsZXQgc3RhcnQgPSBzdGQ6OnRpbWU6Okluc3RhbnQ6Om5vdygpOwogICAgbGV0ICh4LCB5KSA9IHBvczsKICAgIGxldCAoaW1hZ2VfY2FjaGUsIGdseXBoc19jYWNoZSkgPSBjYWNoZXM7CiAgICBsZXQgZGVwdGggPSAwLjA7CiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6bmV3KCk7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udCA9IDA7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udF9zaXplID0gMC4wOwogICAgbGV0IGZvbnRfY29vcmRzOiAmW2kxNl0gPSAmWzAsIDAsIDAsIDBdOwogICAgaWYgbGV0IFNvbWUobGluZSkgPSBsaW5lcy5maXJzdCgpIHsKICAgICAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgICAgICBjdXJyZW50X2ZvbnQgPSBmaXJzdF9ydW4uc3Bhbi5mb250X2lkOwogICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IGZpcnN0X3J1bi5zaXplOwogICAgICAgIH0KICAgIH0KCiAgICBnbHlwaHNfY2FjaGUuc2V0X21heF9oZWlnaHQocmVjdC5oZWlnaHQgYXMgdTE2KTsKCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGxhc3RfcmVuZGVyZWRfZ3JhcGhpYyA9IEhhc2hTZXQ6Om5ldygpOwogICAgbGV0IG11dCBsaW5lX3kgPSAwLiArIHk7CiAgICBmb3IgbGluZSBpbiBsaW5lcyB7CiAgICAgICAgaWYgbGluZS5yZW5kZXJfZGF0YS5ydW5zLmlzX2VtcHR5KCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIGxldCBmaXJzdF9ydW4gPSAmbGluZS5yZW5kZXJfZGF0YS5ydW5zWzBdOwogICAgICAgIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICAgICAgbGV0IGRlc2NlbnQgPSBmaXJzdF9ydW4uZGVzY2VudC5yb3VuZCgpOwogICAgICAgIGxldCBsZWFkaW5nID0gKGZpcnN0X3J1bi5sZWFkaW5nKS5yb3VuZCgpICogMi47CiAgICAgICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICAgICAgbGV0IGJhc2VsaW5lID0gbGluZV95ICsgYXNjZW50OwogICAgICAgIGxpbmVfeSA9IGJhc2VsaW5lICsgZGVzY2VudDsKICAgICAgICBsZXQgcHkgPSBsaW5lX3k7CiAgICAgICAgbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICAgICAgZm9yIHJ1biBpbiAmbGluZS5yZW5kZXJfZGF0YS5ydW5zIHsKICAgICAgICAgICAgZ2x5cGhzLmNsZWFyKCk7CiAgICAgICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICAgICAgbGV0IGNoYXJfd2lkdGggPSBydW4uc3Bhbi53aWR0aDsKCiAgICAgICAgICAgIGxldCBydW5feCA9IHB4OwogICAgICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAgICAgbGV0IHggPSBweDsKICAgICAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgICAgICBweCArPSByZWN0LndpZHRoICogY2hhcl93aWR0aDsKICAgICAgICAgICAgICAgIGdseXBocy5wdXNoKEdseXBoIHsKICAgICAgICAgICAgICAgICAgICBpZDogZ2x5cGguc2ltcGxlX2RhdGEoKS4wLAogICAgICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICAgICAgeSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGZvbnRfc2l6ZTogcnVuLnNpemUsCiAgICAgICAgICAgICAgICBjb2xvcjogcnVuLnNwYW4uY29sb3IsCiAgICAgICAgICAgICAgICBjdXJzb3I6IHJ1bi5zcGFuLmN1cnNvciwKICAgICAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IHJ1bi5zcGFuLmJhY2tncm91bmRfY29sb3IsCiAgICAgICAgICAgICAgICBiYXNlbGluZTogcHksCiAgICAgICAgICAgICAgICB0b3BsaW5lOiBweSAtIGFzY2VudCwKICAgICAgICAgICAgICAgIGxpbmVfaGVpZ2h0LAogICAgICAgICAgICAgICAgYWR2YW5jZTogcHggLSBydW5feCwKICAgICAgICAgICAgICAgIGRlY29yYXRpb246IHJ1bi5zcGFuLmRlY29yYXRpb24sCiAgICAgICAgICAgICAgICBkZWNvcmF0aW9uX2NvbG9yOiBydW4uc3Bhbi5kZWNvcmF0aW9uX2NvbG9yLAogICAgICAgICAgICB9OwoKICAgICAgICAgICAgaWYgZm9udCAhPSBjdXJyZW50X2ZvbnQgfHwgc3R5bGUuZm9udF9zaXplICE9IGN1cnJlbnRfZm9udF9zaXplIHsKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udCA9IGZvbnQ7CiAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IHN0eWxlLmZvbnRfc2l6ZTsKCiAgICAgICAgICAgICAgICBzZXNzaW9uID0gZ2x5cGhzX2NhY2hlLnNlc3Npb24oCiAgICAgICAgICAgICAgICAgICAgaW1hZ2VfY2FjaGUsCiAgICAgICAgICAgICAgICAgICAgY3VycmVudF9mb250LAogICAgICAgICAgICAgICAgICAgIGZvbnRfbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgICAgICBzdHlsZS5mb250X3NpemUsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiBsZXQgU29tZShncmFwaGljKSA9IHJ1bi5zcGFuLm1lZGlhIHsKICAgICAgICAgICAgICAgIGlmICFsYXN0X3JlbmRlcmVkX2dyYXBoaWMuY29udGFpbnMoJmdyYXBoaWMuaWQpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0X3ggPSBncmFwaGljLm9mZnNldF94IGFzIGYzMjsKICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0X3kgPSBncmFwaGljLm9mZnNldF95IGFzIGYzMjsKCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MudG9wX2xheWVyLnB1c2goR3JhcGhpY1JlbmRlclJlcXVlc3QgewogICAgICAgICAgICAgICAgICAgICAgICBpZDogZ3JhcGhpYy5pZCwKICAgICAgICAgICAgICAgICAgICAgICAgcG9zX3g6IHJ1bl94IC0gb2Zmc2V0X3gsCiAgICAgICAgICAgICAgICAgICAgICAgIHBvc195OiBzdHlsZS50b3BsaW5lIC0gb2Zmc2V0X3ksCiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBOb25lLAogICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgbGFzdF9yZW5kZXJlZF9ncmFwaGljLmluc2VydChncmFwaGljLmlkKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29tcC5kcmF3X3J1bigKICAgICAgICAgICAgICAgICZtdXQgc2Vzc2lvbiwKICAgICAgICAgICAgICAgIFJlY3Q6Om5ldyhydW5feCwgcHksIHN0eWxlLmFkdmFuY2UsIDEuKSwKICAgICAgICAgICAgICAgIGRlcHRoLAogICAgICAgICAgICAgICAgJnN0eWxlLAogICAgICAgICAgICAgICAgJmdseXBocywKICAgICAgICAgICAgKTsKICAgICAgICB9CiAgICB9CgogICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgLy8gcHJpbnRsbiEoIiAtIGRyYXdfbGF5b3V0KCkgaXM6IHs6P31cbiIsIGR1cmF0aW9uKTsKfQoKI1tpbmxpbmVdCmZuIGZldGNoX2RpbWVuc2lvbnMoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lOiAmY3JhdGU6OmxheW91dDo6QnVpbGRlckxpbmUsCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKKSAtPiBTdWdhckRpbWVuc2lvbnMgewogICAgbGV0IHggPSAwLjsKICAgIGxldCB5ID0gMC47CgogICAgbGV0IChpbWFnZV9jYWNoZSwgZ2x5cGhzX2NhY2hlKSA9IGNhY2hlczsKICAgIGxldCBtdXQgY3VycmVudF9mb250ID0gMDsKICAgIGxldCBtdXQgY3VycmVudF9mb250X3NpemUgPSAwLjA7CiAgICBsZXQgZm9udF9jb29yZHM6ICZbaTE2XSA9ICZbMCwgMCwgMCwgMF07CiAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgIGN1cnJlbnRfZm9udCA9IGZpcnN0X3J1bi5zcGFuLmZvbnRfaWQ7CiAgICAgICAgY3VycmVudF9mb250X3NpemUgPSBmaXJzdF9ydW4uc2l6ZTsKICAgIH0KCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6d2l0aF9jYXBhY2l0eSgzKTsKICAgIGxldCBtdXQgZGltZW5zaW9uID0gU3VnYXJEaW1lbnNpb25zOjpkZWZhdWx0KCk7CiAgICBsZXQgZmlyc3RfcnVuID0gJmxpbmUucmVuZGVyX2RhdGEucnVuc1swXTsKICAgIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICBsZXQgZGVzY2VudCA9IGZpcnN0X3J1bi5kZXNjZW50LnJvdW5kKCk7CiAgICBsZXQgbGVhZGluZyA9IChmaXJzdF9ydW4ubGVhZGluZykucm91bmQoKSAqIDIuOwogICAgLy8gbGV0IG11dCBweCA9IHggKyBsaW5lLm9mZnNldCgpOwogICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICBsZXQgcHkgPSBhc2NlbnQgKyB5OwogICAgbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICBmb3IgcnVuIGluICZsaW5lLnJlbmRlcl9kYXRhLnJ1bnMgewogICAgICAgIGxldCBjaGFyX3dpZHRoID0gcnVuLnNwYW4ud2lkdGg7CgogICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICBsZXQgcnVuX3ggPSBweDsKICAgICAgICBnbHlwaHMuY2xlYXIoKTsKICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAvLyBsZXQgeCA9IHB4ICsgZ2x5cGgueDsKICAgICAgICAgICAgLy8gbGV0IHkgPSBweSAtIGdseXBoLnk7CiAgICAgICAgICAgIGxldCB4ID0gcHg7CiAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgIC8vIHB4ICs9IGdseXBoLmFkdmFuY2UKICAgICAgICAgICAgcHggKz0gZ2x5cGguc2ltcGxlX2RhdGEoKS4xICogY2hhcl93aWR0aDsKICAgICAgICAgICAgZ2x5cGhzLnB1c2goR2x5cGggewogICAgICAgICAgICAgICAgaWQ6IGdseXBoLnNpbXBsZV9kYXRhKCkuMCwKICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICB5LAogICAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgbGV0IGNvbG9yID0gcnVuLnNwYW4uY29sb3I7CgogICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgICAgICBmb250X3NpemU6IHJ1bi5zaXplLAogICAgICAgICAgICBjb2xvciwKICAgICAgICAgICAgY3Vyc29yOiBydW4uc3Bhbi5jdXJzb3IsCiAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IE5vbmUsCiAgICAgICAgICAgIGJhc2VsaW5lOiBweSwKICAgICAgICAgICAgdG9wbGluZTogcHkgLSBhc2NlbnQsCiAgICAgICAgICAgIGxpbmVfaGVpZ2h0LAogICAgICAgICAgICBhZHZhbmNlOiBweCAtIHJ1bl94LAogICAgICAgICAgICBkZWNvcmF0aW9uOiBOb25lLAogICAgICAgICAgICBkZWNvcmF0aW9uX2NvbG9yOiBOb25lLAogICAgICAgIH07CgogICAgICAgIGlmIHN0eWxlLmFkdmFuY2UgPiAwLiAmJiBsaW5lX2hlaWdodCA+IDAuIHsKICAgICAgICAgICAgZGltZW5zaW9uLndpZHRoID0gc3R5bGUuYWR2YW5jZS5yb3VuZCgpOwogICAgICAgICAgICBkaW1lbnNpb24uaGVpZ2h0ID0gbGluZV9oZWlnaHQucm91bmQoKTsKICAgICAgICB9CgogICAgICAgIGlmIGZvbnQgIT0gY3VycmVudF9mb250IHx8IHN0eWxlLmZvbnRfc2l6ZSAhPSBjdXJyZW50X2ZvbnRfc2l6ZSB7CiAgICAgICAgICAgIGN1cnJlbnRfZm9udCA9IGZvbnQ7CiAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplID0gc3R5bGUuZm9udF9zaXplOwoKICAgICAgICAgICAgc2Vzc2lvbiA9IGdseXBoc19jYWNoZS5zZXNzaW9uKAogICAgICAgICAgICAgICAgaW1hZ2VfY2FjaGUsCiAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgICAgICAgICBmb250X2xpYnJhcnksCiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgICAgICAgICApOwogICAgICAgIH0KCiAgICAgICAgY29tcC5kcmF3X3J1bigKICAgICAgICAgICAgJm11dCBzZXNzaW9uLAogICAgICAgICAgICBSZWN0OjpuZXcocnVuX3gsIHB5LCBzdHlsZS5hZHZhbmNlLCAxLiksCiAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgJnN0eWxlLAogICAgICAgICAgICAmZ2x5cGhzLAogICAgICAgICk7CiAgICB9CgogICAgZGltZW5zaW9uCn0KCiNbaW5saW5lXQpmbiBuZXh0X2NvcHlfYnVmZmVyX3NpemUoc2l6ZTogdTY0KSAtPiB1NjQgewogICAgbGV0IGFsaWduX21hc2sgPSB3Z3B1OjpDT1BZX0JVRkZFUl9BTElHTk1FTlQgLSAxOwogICAgKChzaXplLm5leHRfcG93ZXJfb2ZfdHdvKCkgKyBhbGlnbl9tYXNrKSAmICFhbGlnbl9tYXNrKQogICAgICAgIC5tYXgod2dwdTo6Q09QWV9CVUZGRVJfQUxJR05NRU5UKQp9CgAAAAAAAAAAuFYAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACZPwAAAAAAAJk/AAAAAAAAAAAAAAAA8L8" - ], - [ - 140, - 1, - "toggle_comment", - { - "block": false - }, - "AQAAALU/AAAAAAAAtT8AAAAAAAADAAAALy8g", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADXPwAAAAAAANc/AAAAAAAAAAAAAAAA8L8" - ], - [ - 149, - 1, - "paste", - null, - "AgAAAHpEAAAAAAAAgEQAAAAAAAAAAAAAgEQAAAAAAACARAAAAAAAAAsAAAByZWN0LmhlaWdodA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB6RAAAAAAAAIVEAAAAAAAAAAAAAAAA8L8" - ], - [ - 178, - 1, - "revert", - null, - "AwAAAAAAAAAAAAAAAAAAAAAAAACwVgAAbW9kIGJhdGNoOwptb2QgY29tcG9zaXRvcjsKbW9kIGltYWdlX2NhY2hlOwpwdWIgbW9kIHRleHQ7Cgp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OmNvcmU6Om9ydGhvZ3JhcGhpY19wcm9qZWN0aW9uOwp1c2UgY3JhdGU6OmNvbXBvbmVudHM6OnJpY2hfdGV4dDo6aW1hZ2VfY2FjaGU6OntHbHlwaENhY2hlLCBJbWFnZUNhY2hlfTsKdXNlIGNyYXRlOjpjb250ZXh0OjpDb250ZXh0Owp1c2UgY3JhdGU6OmZvbnQ6OkZvbnRMaWJyYXJ5Owp1c2UgY3JhdGU6OmxheW91dDo6U3VnYXJEaW1lbnNpb25zOwp1c2UgY3JhdGU6OnN1Z2FybG9hZjo6Z3JhcGhpY3M6OkdyYXBoaWNSZW5kZXJSZXF1ZXN0Owp1c2UgY3JhdGU6OkdyYXBoaWNzOwp1c2UgY29tcG9zaXRvcjo6e0NvbXBvc2l0b3IsIERpc3BsYXlMaXN0LCBSZWN0LCBWZXJ0ZXh9Owp1c2Ugc3RkOjpjb2xsZWN0aW9uczo6SGFzaFNldDsKdXNlIHN0ZDo6e2JvcnJvdzo6Q293LCBtZW19Owp1c2UgdGV4dDo6e0dseXBoLCBUZXh0UnVuU3R5bGV9Owp1c2Ugd2dwdTo6dXRpbDo6RGV2aWNlRXh0OwoKLy8gTm90ZTogY3VycmVudGx5IGl0J3MgdXNpbmcgSW5kZXhlZCBkcmF3aW5nIGluc3RlYWQgb2YgSW5zdGFuY2UgZHJhd2luZyBjb3VsZCBiZSB3b3J0aCB0bwovLyBldmFsdWF0ZSBpZiB3b3VsZCBtYWtlIHNlbnNlIG1vdmUgdG8gaW5zdGFuY2UgZHJhd2luZyBpbnN0ZWFkCi8vIGh0dHBzOi8vbWF0aC5od3MuZWR1L2dyYXBoaWNzYm9vay9jOS9zMi5odG1sCi8vIGh0dHBzOi8vZG9jcy5ycy93Z3B1L2xhdGVzdC93Z3B1L2VudW0uVmVydGV4U3RlcE1vZGUuaHRtbAoKcHViIGNvbnN0IEJMRU5EOiBPcHRpb248d2dwdTo6QmxlbmRTdGF0ZT4gPSBTb21lKHdncHU6OkJsZW5kU3RhdGUgewogICAgY29sb3I6IHdncHU6OkJsZW5kQ29tcG9uZW50IHsKICAgICAgICBzcmNfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6U3JjQWxwaGEsCiAgICAgICAgZHN0X2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZU1pbnVzU3JjQWxwaGEsCiAgICAgICAgb3BlcmF0aW9uOiB3Z3B1OjpCbGVuZE9wZXJhdGlvbjo6QWRkLAogICAgfSwKICAgIGFscGhhOiB3Z3B1OjpCbGVuZENvbXBvbmVudCB7CiAgICAgICAgc3JjX2ZhY3Rvcjogd2dwdTo6QmxlbmRGYWN0b3I6Ok9uZSwKICAgICAgICBkc3RfZmFjdG9yOiB3Z3B1OjpCbGVuZEZhY3Rvcjo6T25lTWludXNTcmNBbHBoYSwKICAgICAgICBvcGVyYXRpb246IHdncHU6OkJsZW5kT3BlcmF0aW9uOjpBZGQsCiAgICB9LAp9KTsKCnB1YiBzdHJ1Y3QgUmljaFRleHRCcnVzaCB7CiAgICB2ZXJ0ZXhfYnVmZmVyOiB3Z3B1OjpCdWZmZXIsCiAgICBjb25zdGFudF9iaW5kX2dyb3VwOiB3Z3B1OjpCaW5kR3JvdXAsCiAgICBsYXlvdXRfYmluZF9ncm91cDogd2dwdTo6QmluZEdyb3VwLAogICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0OiB3Z3B1OjpCaW5kR3JvdXBMYXlvdXQsCiAgICB0cmFuc2Zvcm06IHdncHU6OkJ1ZmZlciwKICAgIHBpcGVsaW5lOiB3Z3B1OjpSZW5kZXJQaXBlbGluZSwKICAgIGluZGV4X2J1ZmZlcjogd2dwdTo6QnVmZmVyLAogICAgaW5kZXhfYnVmZmVyX3NpemU6IHU2NCwKICAgIGN1cnJlbnRfdHJhbnNmb3JtOiBbZjMyOyAxNl0sCiAgICBjb21wOiBDb21wb3NpdG9yLAogICAgZGxpc3Q6IERpc3BsYXlMaXN0LAogICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXI6IHVzaXplLAogICAgdGV4dHVyZXNfdmVyc2lvbjogdXNpemUsCiAgICBpbWFnZXM6IEltYWdlQ2FjaGUsCiAgICBnbHlwaHM6IEdseXBoQ2FjaGUsCn0KCmltcGwgUmljaFRleHRCcnVzaCB7CiAgICBwdWIgZm4gbmV3KGNvbnRleHQ6ICZDb250ZXh0KSAtPiBTZWxmIHsKICAgICAgICBsZXQgZGV2aWNlID0gJmNvbnRleHQuZGV2aWNlOwogICAgICAgIGxldCBkbGlzdCA9IERpc3BsYXlMaXN0OjpuZXcoKTsKICAgICAgICBsZXQgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIgPSAyXzAwMDsKCiAgICAgICAgbGV0IGN1cnJlbnRfdHJhbnNmb3JtID0KICAgICAgICAgICAgb3J0aG9ncmFwaGljX3Byb2plY3Rpb24oY29udGV4dC5zaXplLndpZHRoLCBjb250ZXh0LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtID0gZGV2aWNlLmNyZWF0ZV9idWZmZXJfaW5pdCgmd2dwdTo6dXRpbDo6QnVmZmVySW5pdERlc2NyaXB0b3IgewogICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgY29udGVudHM6IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZjdXJyZW50X3RyYW5zZm9ybSksCiAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlVOSUZPUk0gfCB3Z3B1OjpCdWZmZXJVc2FnZXM6OkNPUFlfRFNULAogICAgICAgIH0pOwoKICAgICAgICAvLyBDcmVhdGUgcGlwZWxpbmUgbGF5b3V0CiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9iaW5kX2dyb3VwX2xheW91dCgmd2dwdTo6QmluZEdyb3VwTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbCiAgICAgICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwTGF5b3V0RW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICB2aXNpYmlsaXR5OiB3Z3B1OjpTaGFkZXJTdGFnZXM6OlZFUlRFWCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpCdWZmZXIgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJ1ZmZlckJpbmRpbmdUeXBlOjpVbmlmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzX2R5bmFtaWNfb2Zmc2V0OiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbl9iaW5kaW5nX3NpemU6IHdncHU6OkJ1ZmZlclNpemU6Om5ldyhtZW06OnNpemVfb2Y6OjwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZjMyOyAxNl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+KAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzIHdncHU6OkJ1ZmZlckFkZHJlc3MpLAogICAgICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgICAgICBjb3VudDogTm9uZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgYmluZGluZzogMSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlzaWJpbGl0eTogd2dwdTo6U2hhZGVyU3RhZ2VzOjpWRVJURVgKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwgd2dwdTo6U2hhZGVyU3RhZ2VzOjpGUkFHTUVOVCwKICAgICAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpTYW1wbGVyKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgd2dwdTo6U2FtcGxlckJpbmRpbmdUeXBlOjpGaWx0ZXJpbmcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGxheW91dF9iaW5kX2dyb3VwX2xheW91dCA9CiAgICAgICAgICAgIGRldmljZS5jcmVhdGVfYmluZF9ncm91cF9sYXlvdXQoJndncHU6OkJpbmRHcm91cExheW91dERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgICAgICBlbnRyaWVzOiAmW3dncHU6OkJpbmRHcm91cExheW91dEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6IHdncHU6OlNoYWRlclN0YWdlczo6RlJBR01FTlQsCiAgICAgICAgICAgICAgICAgICAgdHk6IHdncHU6OkJpbmRpbmdUeXBlOjpUZXh0dXJlIHsKICAgICAgICAgICAgICAgICAgICAgICAgc2FtcGxlX3R5cGU6IHdncHU6OlRleHR1cmVTYW1wbGVUeXBlOjpGbG9hdCB7IGZpbHRlcmFibGU6IHRydWUgfSwKICAgICAgICAgICAgICAgICAgICAgICAgdmlld19kaW1lbnNpb246IHdncHU6OlRleHR1cmVWaWV3RGltZW5zaW9uOjpEMiwKICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlzYW1wbGVkOiBmYWxzZSwKICAgICAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgICAgIGNvdW50OiBOb25lLAogICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgIH0pOwoKICAgICAgICBsZXQgcGlwZWxpbmVfbGF5b3V0ID0KICAgICAgICAgICAgZGV2aWNlLmNyZWF0ZV9waXBlbGluZV9sYXlvdXQoJndncHU6OlBpcGVsaW5lTGF5b3V0RGVzY3JpcHRvciB7CiAgICAgICAgICAgICAgICBsYWJlbDogTm9uZSwKICAgICAgICAgICAgICAgIHB1c2hfY29uc3RhbnRfcmFuZ2VzOiAmW10sCiAgICAgICAgICAgICAgICBiaW5kX2dyb3VwX2xheW91dHM6ICZbCiAgICAgICAgICAgICAgICAgICAgJmNvbnN0YW50X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgICZsYXlvdXRfYmluZF9ncm91cF9sYXlvdXQsCiAgICAgICAgICAgICAgICBdLAogICAgICAgICAgICB9KTsKCiAgICAgICAgbGV0IGltYWdlcyA9IEltYWdlQ2FjaGU6Om5ldyhjb250ZXh0KTsKCiAgICAgICAgbGV0IHNhbXBsZXIgPSBkZXZpY2UuY3JlYXRlX3NhbXBsZXIoJndncHU6OlNhbXBsZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3U6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3Y6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgYWRkcmVzc19tb2RlX3c6IHdncHU6OkFkZHJlc3NNb2RlOjpDbGFtcFRvRWRnZSwKICAgICAgICAgICAgbWFnX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWluX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbWlwbWFwX2ZpbHRlcjogd2dwdTo6RmlsdGVyTW9kZTo6TmVhcmVzdCwKICAgICAgICAgICAgbG9kX21pbl9jbGFtcDogMGYzMiwKICAgICAgICAgICAgbG9kX21heF9jbGFtcDogMGYzMiwKICAgICAgICAgICAgLi5EZWZhdWx0OjpkZWZhdWx0KCkKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGNvbnN0YW50X2JpbmRfZ3JvdXAgPSBkZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICBsYXlvdXQ6ICZjb25zdGFudF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlsKICAgICAgICAgICAgICAgIHdncHU6OkJpbmRHcm91cEVudHJ5IHsKICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgIHJlc291cmNlOiB3Z3B1OjpCaW5kaW5nUmVzb3VyY2U6OkJ1ZmZlcih3Z3B1OjpCdWZmZXJCaW5kaW5nIHsKICAgICAgICAgICAgICAgICAgICAgICAgYnVmZmVyOiAmdHJhbnNmb3JtLAogICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IDAsCiAgICAgICAgICAgICAgICAgICAgICAgIHNpemU6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgIGJpbmRpbmc6IDEsCiAgICAgICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6U2FtcGxlcigmc2FtcGxlciksCiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICBdLAogICAgICAgICAgICBsYWJlbDogU29tZSgicmljaF90ZXh0Ojpjb25zdGFudF9iaW5kX2dyb3VwIiksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBsYXlvdXRfYmluZF9ncm91cCA9IGRldmljZS5jcmVhdGVfYmluZF9ncm91cCgmd2dwdTo6QmluZEdyb3VwRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxheW91dDogJmxheW91dF9iaW5kX2dyb3VwX2xheW91dCwKICAgICAgICAgICAgZW50cmllczogJlt3Z3B1OjpCaW5kR3JvdXBFbnRyeSB7CiAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgcmVzb3VyY2U6IHdncHU6OkJpbmRpbmdSZXNvdXJjZTo6VGV4dHVyZVZpZXcoJmltYWdlcy50ZXh0dXJlX3ZpZXcpLAogICAgICAgICAgICB9XSwKICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6bGF5b3V0X2JpbmRfZ3JvdXAiKSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHNoYWRlciA9IGRldmljZS5jcmVhdGVfc2hhZGVyX21vZHVsZSh3Z3B1OjpTaGFkZXJNb2R1bGVEZXNjcmlwdG9yIHsKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIHNvdXJjZTogd2dwdTo6U2hhZGVyU291cmNlOjpXZ3NsKENvdzo6Qm9ycm93ZWQoaW5jbHVkZV9zdHIhKAogICAgICAgICAgICAgICAgInJpY2hfdGV4dC53Z3NsIgogICAgICAgICAgICApKSksCiAgICAgICAgfSk7CgogICAgICAgIGxldCBwaXBlbGluZSA9IGRldmljZS5jcmVhdGVfcmVuZGVyX3BpcGVsaW5lKCZ3Z3B1OjpSZW5kZXJQaXBlbGluZURlc2NyaXB0b3IgewogICAgICAgICAgICBjYWNoZTogTm9uZSwKICAgICAgICAgICAgbGFiZWw6IE5vbmUsCiAgICAgICAgICAgIGxheW91dDogU29tZSgmcGlwZWxpbmVfbGF5b3V0KSwKICAgICAgICAgICAgdmVydGV4OiB3Z3B1OjpWZXJ0ZXhTdGF0ZSB7CiAgICAgICAgICAgICAgICBjb21waWxhdGlvbl9vcHRpb25zOiB3Z3B1OjpQaXBlbGluZUNvbXBpbGF0aW9uT3B0aW9uczo6ZGVmYXVsdCgpLAogICAgICAgICAgICAgICAgbW9kdWxlOiAmc2hhZGVyLAogICAgICAgICAgICAgICAgZW50cnlfcG9pbnQ6IFNvbWUoInZzX21haW4iKSwKICAgICAgICAgICAgICAgIGJ1ZmZlcnM6ICZbd2dwdTo6VmVydGV4QnVmZmVyTGF5b3V0IHsKICAgICAgICAgICAgICAgICAgICBhcnJheV9zdHJpZGU6IG1lbTo6c2l6ZV9vZjo6PFZlcnRleD4oKSBhcyB1NjQsCiAgICAgICAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLnJzL3dncHUvbGF0ZXN0L3dncHUvZW51bS5WZXJ0ZXhTdGVwTW9kZS5odG1sCiAgICAgICAgICAgICAgICAgICAgc3RlcF9tb2RlOiB3Z3B1OjpWZXJ0ZXhTdGVwTW9kZTo6VmVydGV4LAogICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXM6ICZ3Z3B1Ojp2ZXJ0ZXhfYXR0cl9hcnJheSEoCiAgICAgICAgICAgICAgICAgICAgICAgIDAgPT4gRmxvYXQzMngzLAogICAgICAgICAgICAgICAgICAgICAgICAxID0+IEZsb2F0MzJ4NCwKICAgICAgICAgICAgICAgICAgICAgICAgMiA9PiBGbG9hdDMyeDIsCiAgICAgICAgICAgICAgICAgICAgICAgIDMgPT4gU2ludDMyeDIsCiAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgIH1dLAogICAgICAgICAgICB9LAogICAgICAgICAgICBmcmFnbWVudDogU29tZSh3Z3B1OjpGcmFnbWVudFN0YXRlIHsKICAgICAgICAgICAgICAgIGNvbXBpbGF0aW9uX29wdGlvbnM6IHdncHU6OlBpcGVsaW5lQ29tcGlsYXRpb25PcHRpb25zOjpkZWZhdWx0KCksCiAgICAgICAgICAgICAgICBtb2R1bGU6ICZzaGFkZXIsCiAgICAgICAgICAgICAgICBlbnRyeV9wb2ludDogU29tZSgiZnNfbWFpbiIpLAogICAgICAgICAgICAgICAgdGFyZ2V0czogJltTb21lKHdncHU6OkNvbG9yVGFyZ2V0U3RhdGUgewogICAgICAgICAgICAgICAgICAgIGZvcm1hdDogY29udGV4dC5mb3JtYXQsCiAgICAgICAgICAgICAgICAgICAgYmxlbmQ6IEJMRU5ELAogICAgICAgICAgICAgICAgICAgIHdyaXRlX21hc2s6IHdncHU6OkNvbG9yV3JpdGVzOjpBTEwsCiAgICAgICAgICAgICAgICB9KV0sCiAgICAgICAgICAgIH0pLAogICAgICAgICAgICBwcmltaXRpdmU6IHdncHU6OlByaW1pdGl2ZVN0YXRlIHsKICAgICAgICAgICAgICAgIHRvcG9sb2d5OiB3Z3B1OjpQcmltaXRpdmVUb3BvbG9neTo6VHJpYW5nbGVMaXN0LAogICAgICAgICAgICAgICAgc3RyaXBfaW5kZXhfZm9ybWF0OiBOb25lLAogICAgICAgICAgICAgICAgZnJvbnRfZmFjZTogd2dwdTo6RnJvbnRGYWNlOjpDY3csCiAgICAgICAgICAgICAgICBjdWxsX21vZGU6IE5vbmUsCiAgICAgICAgICAgICAgICBwb2x5Z29uX21vZGU6IHdncHU6OlBvbHlnb25Nb2RlOjpGaWxsLAogICAgICAgICAgICAgICAgdW5jbGlwcGVkX2RlcHRoOiBmYWxzZSwKICAgICAgICAgICAgICAgIGNvbnNlcnZhdGl2ZTogZmFsc2UsCiAgICAgICAgICAgIH0sCiAgICAgICAgICAgIGRlcHRoX3N0ZW5jaWw6IE5vbmUsCiAgICAgICAgICAgIG11bHRpc2FtcGxlOiB3Z3B1OjpNdWx0aXNhbXBsZVN0YXRlOjpkZWZhdWx0KCksCiAgICAgICAgICAgIG11bHRpdmlldzogTm9uZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IHZlcnRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6Okluc3RhbmNlcyBCdWZmZXIiKSwKICAgICAgICAgICAgc2l6ZTogbWVtOjpzaXplX29mOjo8VmVydGV4PigpIGFzIHU2NCAqIHN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgdXNhZ2U6IHdncHU6OkJ1ZmZlclVzYWdlczo6VkVSVEVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgbWFwcGVkX2F0X2NyZWF0aW9uOiBmYWxzZSwKICAgICAgICB9KTsKCiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplOiAmW3UzMl0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmZGxpc3QuaW5kaWNlcyk7CiAgICAgICAgbGV0IGluZGV4X2J1ZmZlcl9zaXplID0gaW5kZXhfYnVmZmVyX3NpemUubGVuKCkgYXMgdTY0OwogICAgICAgIGxldCBpbmRleF9idWZmZXIgPSBkZXZpY2UuY3JlYXRlX2J1ZmZlcigmd2dwdTo6QnVmZmVyRGVzY3JpcHRvciB7CiAgICAgICAgICAgIGxhYmVsOiBTb21lKCJyaWNoX3RleHQ6OkluZGljZXMgQnVmZmVyIiksCiAgICAgICAgICAgIHNpemU6IGluZGV4X2J1ZmZlcl9zaXplLAogICAgICAgICAgICB1c2FnZTogd2dwdTo6QnVmZmVyVXNhZ2VzOjpJTkRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogZmFsc2UsCiAgICAgICAgfSk7CgogICAgICAgIFJpY2hUZXh0QnJ1c2ggewogICAgICAgICAgICBsYXlvdXRfYmluZF9ncm91cCwKICAgICAgICAgICAgbGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICBjb25zdGFudF9iaW5kX2dyb3VwLAogICAgICAgICAgICBpbmRleF9idWZmZXJfc2l6ZSwKICAgICAgICAgICAgaW5kZXhfYnVmZmVyLAogICAgICAgICAgICBjb21wOiBDb21wb3NpdG9yOjpuZXcoKSwKICAgICAgICAgICAgaW1hZ2VzLAogICAgICAgICAgICB0ZXh0dXJlc192ZXJzaW9uOiAwLAogICAgICAgICAgICBnbHlwaHM6IEdseXBoQ2FjaGU6Om5ldygpLAogICAgICAgICAgICBkbGlzdCwKICAgICAgICAgICAgdHJhbnNmb3JtLAogICAgICAgICAgICBwaXBlbGluZSwKICAgICAgICAgICAgdmVydGV4X2J1ZmZlciwKICAgICAgICAgICAgc3VwcG9ydGVkX3ZlcnRleF9idWZmZXIsCiAgICAgICAgICAgIGN1cnJlbnRfdHJhbnNmb3JtLAogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBwcmVwYXJlKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBjb250ZXh0OiAmbXV0IGNyYXRlOjpjb250ZXh0OjpDb250ZXh0LAogICAgICAgIHN0YXRlOiAmY3JhdGU6OnN1Z2FybG9hZjo6c3RhdGU6OlN1Z2FyU3RhdGUsCiAgICAgICAgZ3JhcGhpY3M6ICZtdXQgR3JhcGhpY3MsCiAgICApIHsKICAgICAgICBpZiBzdGF0ZS5yaWNoX3RleHRzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIHNlbGYuY29tcC5iZWdpbigpOwogICAgICAgIGxldCBsaWJyYXJ5ID0gc3RhdGUuY29tcG9zaXRvcnMuYWR2YW5jZWQuZm9udF9saWJyYXJ5KCk7CiAgICAgICAgZm9yIHJpY2hfdGV4dCBpbiAmc3RhdGUucmljaF90ZXh0cyB7CiAgICAgICAgICAgIGlmIGxldCBTb21lKHJ0KSA9IHN0YXRlLmNvbXBvc2l0b3JzLmFkdmFuY2VkLmdldF9yaWNoX3RleHQoJnJpY2hfdGV4dC5pZCkgewogICAgICAgICAgICAgICAgbGV0IHBvc2l0aW9uID0gKAogICAgICAgICAgICAgICAgICAgIHJpY2hfdGV4dC5wb3NpdGlvblswXSAqIHN0YXRlLnN0eWxlLnNjYWxlX2ZhY3RvciwKICAgICAgICAgICAgICAgICAgICByaWNoX3RleHQucG9zaXRpb25bMV0gKiBzdGF0ZS5zdHlsZS5zY2FsZV9mYWN0b3IsCiAgICAgICAgICAgICAgICApOwoKICAgICAgICAgICAgICAgIGRyYXdfbGF5b3V0KAogICAgICAgICAgICAgICAgICAgICZtdXQgc2VsZi5jb21wLAogICAgICAgICAgICAgICAgICAgICgmbXV0IHNlbGYuaW1hZ2VzLCAmbXV0IHNlbGYuZ2x5cGhzKSwKICAgICAgICAgICAgICAgICAgICAmcnQubGluZXMsCiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24sCiAgICAgICAgICAgICAgICAgICAgbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICAmcnQubGF5b3V0LmRpbWVuc2lvbnMsCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBzZWxmLmRsaXN0LmNsZWFyKCk7CiAgICAgICAgc2VsZi5pbWFnZXMucHJvY2Vzc19hdGxhc2VzKGNvbnRleHQpOwogICAgICAgIHNlbGYuY29tcC5maW5pc2goJm11dCBzZWxmLmRsaXN0KTsKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBkaW1lbnNpb25zKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgICAgICByZW5kZXJfZGF0YTogJmNyYXRlOjpsYXlvdXQ6OkJ1aWxkZXJMaW5lLAogICAgKSAtPiBPcHRpb248U3VnYXJEaW1lbnNpb25zPiB7CiAgICAgICAgc2VsZi5jb21wLmJlZ2luKCk7CgogICAgICAgIGxldCBkaW1lbnNpb24gPSBmZXRjaF9kaW1lbnNpb25zKAogICAgICAgICAgICAmbXV0IHNlbGYuY29tcCwKICAgICAgICAgICAgKCZtdXQgc2VsZi5pbWFnZXMsICZtdXQgc2VsZi5nbHlwaHMpLAogICAgICAgICAgICByZW5kZXJfZGF0YSwKICAgICAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgICk7CiAgICAgICAgaWYgZGltZW5zaW9uLmhlaWdodCA+IDAuICYmIGRpbWVuc2lvbi53aWR0aCA+IDAuIHsKICAgICAgICAgICAgU29tZShkaW1lbnNpb24pCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgTm9uZQogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiByZXNldCgmbXV0IHNlbGYpIHsKICAgICAgICBzZWxmLmdseXBocyA9IEdseXBoQ2FjaGU6Om5ldygpOwogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHJlbmRlcjwncGFzcz4oCiAgICAgICAgJidwYXNzIG11dCBzZWxmLAogICAgICAgIGN0eDogJm11dCBDb250ZXh0LAogICAgICAgIHJwYXNzOiAmbXV0IHdncHU6OlJlbmRlclBhc3M8J3Bhc3M+LAogICAgKSB7CiAgICAgICAgLy8gbGV0IHN0YXJ0ID0gc3RkOjp0aW1lOjpJbnN0YW50Ojpub3coKTsKICAgICAgICAvLyBUaGVyZSdzIG5vdGhpbmcgdG8gcmVuZGVyCiAgICAgICAgaWYgc2VsZi5kbGlzdC52ZXJ0aWNlcy5pc19lbXB0eSgpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgbGV0IHF1ZXVlID0gJm11dCBjdHgucXVldWU7CgogICAgICAgIGxldCB0cmFuc2Zvcm0gPSBvcnRob2dyYXBoaWNfcHJvamVjdGlvbihjdHguc2l6ZS53aWR0aCwgY3R4LnNpemUuaGVpZ2h0KTsKICAgICAgICBsZXQgdHJhbnNmb3JtX2hhc19jaGFuZ2VkID0gdHJhbnNmb3JtICE9IHNlbGYuY3VycmVudF90cmFuc2Zvcm07CgogICAgICAgIGlmIHRyYW5zZm9ybV9oYXNfY2hhbmdlZCB7CiAgICAgICAgICAgIHF1ZXVlLndyaXRlX2J1ZmZlcigmc2VsZi50cmFuc2Zvcm0sIDAsIGJ5dGVtdWNrOjpieXRlc19vZigmdHJhbnNmb3JtKSk7CiAgICAgICAgICAgIHNlbGYuY3VycmVudF90cmFuc2Zvcm0gPSB0cmFuc2Zvcm07CiAgICAgICAgfQoKICAgICAgICBpZiBzZWxmLmRsaXN0LnZlcnRpY2VzLmxlbigpID4gc2VsZi5zdXBwb3J0ZWRfdmVydGV4X2J1ZmZlciB7CiAgICAgICAgICAgIHNlbGYudmVydGV4X2J1ZmZlci5kZXN0cm95KCk7CgogICAgICAgICAgICBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyID0gc2VsZi5kbGlzdC52ZXJ0aWNlcy5sZW4oKTsKICAgICAgICAgICAgc2VsZi52ZXJ0ZXhfYnVmZmVyID0gY3R4LmRldmljZS5jcmVhdGVfYnVmZmVyKCZ3Z3B1OjpCdWZmZXJEZXNjcmlwdG9yIHsKICAgICAgICAgICAgICAgIGxhYmVsOiBTb21lKCJzdWdhcmxvYWY6OnJpY2hfdGV4dDo6UGlwZWxpbmUgaW5zdGFuY2VzIiksCiAgICAgICAgICAgICAgICBzaXplOiBtZW06OnNpemVfb2Y6OjxWZXJ0ZXg+KCkgYXMgdTY0CiAgICAgICAgICAgICAgICAgICAgKiBzZWxmLnN1cHBvcnRlZF92ZXJ0ZXhfYnVmZmVyIGFzIHU2NCwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OlZFUlRFWCB8IHdncHU6OkJ1ZmZlclVzYWdlczo6Q09QWV9EU1QsCiAgICAgICAgICAgICAgICBtYXBwZWRfYXRfY3JlYXRpb246IGZhbHNlLAogICAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIGxldCB2ZXJ0aWNlc19ieXRlczogJlt1OF0gPSBieXRlbXVjazo6Y2FzdF9zbGljZSgmc2VsZi5kbGlzdC52ZXJ0aWNlcyk7CiAgICAgICAgaWYgIXZlcnRpY2VzX2J5dGVzLmlzX2VtcHR5KCkgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYudmVydGV4X2J1ZmZlciwgMCwgdmVydGljZXNfYnl0ZXMpOwogICAgICAgIH0KCiAgICAgICAgbGV0IGluZGljZXNfcmF3OiAmW3U4XSA9IGJ5dGVtdWNrOjpjYXN0X3NsaWNlKCZzZWxmLmRsaXN0LmluZGljZXMpOwogICAgICAgIGxldCBpbmRpY2VzX3Jhd19zaXplID0gaW5kaWNlc19yYXcubGVuKCkgYXMgdTY0OwoKICAgICAgICBpZiBzZWxmLmluZGV4X2J1ZmZlcl9zaXplID49IGluZGljZXNfcmF3X3NpemUgewogICAgICAgICAgICBxdWV1ZS53cml0ZV9idWZmZXIoJnNlbGYuaW5kZXhfYnVmZmVyLCAwLCBpbmRpY2VzX3Jhdyk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIuZGVzdHJveSgpOwoKICAgICAgICAgICAgbGV0IHNpemUgPSBuZXh0X2NvcHlfYnVmZmVyX3NpemUoaW5kaWNlc19yYXdfc2l6ZSk7CiAgICAgICAgICAgIGxldCBidWZmZXIgPSBjdHguZGV2aWNlLmNyZWF0ZV9idWZmZXIoJndncHU6OkJ1ZmZlckRlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6SW5kaWNlcyIpLAogICAgICAgICAgICAgICAgc2l6ZSwKICAgICAgICAgICAgICAgIHVzYWdlOiB3Z3B1OjpCdWZmZXJVc2FnZXM6OklOREVYIHwgd2dwdTo6QnVmZmVyVXNhZ2VzOjpDT1BZX0RTVCwKICAgICAgICAgICAgICAgIG1hcHBlZF9hdF9jcmVhdGlvbjogdHJ1ZSwKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJ1ZmZlci5zbGljZSguLikuZ2V0X21hcHBlZF9yYW5nZV9tdXQoKVsuLmluZGljZXNfcmF3LmxlbigpXQogICAgICAgICAgICAgICAgLmNvcHlfZnJvbV9zbGljZShpbmRpY2VzX3Jhdyk7CiAgICAgICAgICAgIGJ1ZmZlci51bm1hcCgpOwoKICAgICAgICAgICAgc2VsZi5pbmRleF9idWZmZXIgPSBidWZmZXI7CiAgICAgICAgICAgIHNlbGYuaW5kZXhfYnVmZmVyX3NpemUgPSBzaXplOwogICAgICAgIH0KCiAgICAgICAgaWYgc2VsZi50ZXh0dXJlc192ZXJzaW9uICE9IHNlbGYuaW1hZ2VzLmVudHJpZXMubGVuKCkgewogICAgICAgICAgICBzZWxmLnRleHR1cmVzX3ZlcnNpb24gPSBzZWxmLmltYWdlcy5lbnRyaWVzLmxlbigpOwogICAgICAgICAgICBzZWxmLmxheW91dF9iaW5kX2dyb3VwID0KICAgICAgICAgICAgICAgIGN0eC5kZXZpY2UuY3JlYXRlX2JpbmRfZ3JvdXAoJndncHU6OkJpbmRHcm91cERlc2NyaXB0b3IgewogICAgICAgICAgICAgICAgICAgIGxheW91dDogJnNlbGYubGF5b3V0X2JpbmRfZ3JvdXBfbGF5b3V0LAogICAgICAgICAgICAgICAgICAgIGVudHJpZXM6ICZbd2dwdTo6QmluZEdyb3VwRW50cnkgewogICAgICAgICAgICAgICAgICAgICAgICBiaW5kaW5nOiAwLAogICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZTogd2dwdTo6QmluZGluZ1Jlc291cmNlOjpUZXh0dXJlVmlldygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICZzZWxmLmltYWdlcy50ZXh0dXJlX3ZpZXcsCiAgICAgICAgICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICAgICAgfV0sCiAgICAgICAgICAgICAgICAgICAgbGFiZWw6IFNvbWUoInJpY2hfdGV4dDo6UGlwZWxpbmUgdW5pZm9ybXMiKSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgIH0KCiAgICAgICAgcnBhc3Muc2V0X3BpcGVsaW5lKCZzZWxmLnBpcGVsaW5lKTsKICAgICAgICBycGFzcy5zZXRfYmluZF9ncm91cCgwLCAmc2VsZi5jb25zdGFudF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF9iaW5kX2dyb3VwKDEsICZzZWxmLmxheW91dF9iaW5kX2dyb3VwLCAmW10pOwogICAgICAgIHJwYXNzLnNldF92ZXJ0ZXhfYnVmZmVyKDAsIHNlbGYudmVydGV4X2J1ZmZlci5zbGljZSguLikpOwogICAgICAgIHJwYXNzLnNldF9pbmRleF9idWZmZXIoc2VsZi5pbmRleF9idWZmZXIuc2xpY2UoLi4pLCB3Z3B1OjpJbmRleEZvcm1hdDo6VWludDMyKTsKICAgICAgICBycGFzcy5kcmF3X2luZGV4ZWQoMC4uKHNlbGYuZGxpc3QuaW5kaWNlcy5sZW4oKSBhcyB1MzIpLCAwLCAwLi4xKTsKCiAgICAgICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgICAgIC8vIHByaW50bG4hKCIgLSByaWNoX3RleHQ6OnJlbmRlcigpIGlzOiB7Oj99IiwgZHVyYXRpb24pOwogICAgfQp9CgojW2lubGluZV0KZm4gZHJhd19sYXlvdXQoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lczogJlZlYzxjcmF0ZTo6bGF5b3V0OjpCdWlsZGVyTGluZT4sCiAgICBwb3M6IChmMzIsIGYzMiksCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKICAgIHJlY3Q6ICZTdWdhckRpbWVuc2lvbnMsCiAgICBncmFwaGljczogJm11dCBHcmFwaGljcywKKSB7CiAgICAvLyBsZXQgc3RhcnQgPSBzdGQ6OnRpbWU6Okluc3RhbnQ6Om5vdygpOwogICAgbGV0ICh4LCB5KSA9IHBvczsKICAgIGxldCAoaW1hZ2VfY2FjaGUsIGdseXBoc19jYWNoZSkgPSBjYWNoZXM7CiAgICBsZXQgZGVwdGggPSAwLjA7CiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6bmV3KCk7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udCA9IDA7CiAgICBsZXQgbXV0IGN1cnJlbnRfZm9udF9zaXplID0gMC4wOwogICAgbGV0IGZvbnRfY29vcmRzOiAmW2kxNl0gPSAmWzAsIDAsIDAsIDBdOwogICAgaWYgbGV0IFNvbWUobGluZSkgPSBsaW5lcy5maXJzdCgpIHsKICAgICAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgICAgICBjdXJyZW50X2ZvbnQgPSBmaXJzdF9ydW4uc3Bhbi5mb250X2lkOwogICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IGZpcnN0X3J1bi5zaXplOwogICAgICAgIH0KICAgIH0KCiAgICBnbHlwaHNfY2FjaGUuc2V0X21heF9oZWlnaHQocmVjdC5oZWlnaHQgYXMgdTE2KTsKCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGxhc3RfcmVuZGVyZWRfZ3JhcGhpYyA9IEhhc2hTZXQ6Om5ldygpOwogICAgbGV0IG11dCBsaW5lX3kgPSAwLiArIHk7CiAgICBmb3IgbGluZSBpbiBsaW5lcyB7CiAgICAgICAgaWYgbGluZS5yZW5kZXJfZGF0YS5ydW5zLmlzX2VtcHR5KCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CgogICAgICAgIGxldCBmaXJzdF9ydW4gPSAmbGluZS5yZW5kZXJfZGF0YS5ydW5zWzBdOwogICAgICAgIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICAgICAgLy8gbGV0IGRlc2NlbnQgPSBmaXJzdF9ydW4uZGVzY2VudC5yb3VuZCgpOwogICAgICAgIC8vIGxldCBsZWFkaW5nID0gKGZpcnN0X3J1bi5sZWFkaW5nKS5yb3VuZCgpICogMi47CiAgICAgICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICAgICAgLy8gbGV0IGJhc2VsaW5lID0gbGluZV95ICsgYXNjZW50OwogICAgICAgIC8vIGxpbmVfeSA9IGJhc2VsaW5lICsgZGVzY2VudDsKICAgICAgICBsaW5lX3kgPSBsaW5lX3kgKyByZWN0LmhlaWdodDsKICAgICAgICBsZXQgcHkgPSBsaW5lX3k7CiAgICAgICAgLy8gbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICAgICAgbGV0IGxpbmVfaGVpZ2h0ID0gcmVjdC5oZWlnaHQ7CiAgICAgICAgZm9yIHJ1biBpbiAmbGluZS5yZW5kZXJfZGF0YS5ydW5zIHsKICAgICAgICAgICAgZ2x5cGhzLmNsZWFyKCk7CiAgICAgICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICAgICAgbGV0IGNoYXJfd2lkdGggPSBydW4uc3Bhbi53aWR0aDsKCiAgICAgICAgICAgIGxldCBydW5feCA9IHB4OwogICAgICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAgICAgbGV0IHggPSBweDsKICAgICAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgICAgICBweCArPSByZWN0LndpZHRoICogY2hhcl93aWR0aDsKICAgICAgICAgICAgICAgIGdseXBocy5wdXNoKEdseXBoIHsKICAgICAgICAgICAgICAgICAgICBpZDogZ2x5cGguc2ltcGxlX2RhdGEoKS4wLAogICAgICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICAgICAgeSwKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGZvbnRfc2l6ZTogcnVuLnNpemUsCiAgICAgICAgICAgICAgICBjb2xvcjogcnVuLnNwYW4uY29sb3IsCiAgICAgICAgICAgICAgICBjdXJzb3I6IHJ1bi5zcGFuLmN1cnNvciwKICAgICAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IHJ1bi5zcGFuLmJhY2tncm91bmRfY29sb3IsCiAgICAgICAgICAgICAgICBiYXNlbGluZTogcHksCiAgICAgICAgICAgICAgICB0b3BsaW5lOiBweSAtIGFzY2VudCwKICAgICAgICAgICAgICAgIGxpbmVfaGVpZ2h0LAogICAgICAgICAgICAgICAgYWR2YW5jZTogcHggLSBydW5feCwKICAgICAgICAgICAgICAgIGRlY29yYXRpb246IHJ1bi5zcGFuLmRlY29yYXRpb24sCiAgICAgICAgICAgICAgICBkZWNvcmF0aW9uX2NvbG9yOiBydW4uc3Bhbi5kZWNvcmF0aW9uX2NvbG9yLAogICAgICAgICAgICB9OwoKICAgICAgICAgICAgaWYgZm9udCAhPSBjdXJyZW50X2ZvbnQgfHwgc3R5bGUuZm9udF9zaXplICE9IGN1cnJlbnRfZm9udF9zaXplIHsKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udCA9IGZvbnQ7CiAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnRfc2l6ZSA9IHN0eWxlLmZvbnRfc2l6ZTsKCiAgICAgICAgICAgICAgICBzZXNzaW9uID0gZ2x5cGhzX2NhY2hlLnNlc3Npb24oCiAgICAgICAgICAgICAgICAgICAgaW1hZ2VfY2FjaGUsCiAgICAgICAgICAgICAgICAgICAgY3VycmVudF9mb250LAogICAgICAgICAgICAgICAgICAgIGZvbnRfbGlicmFyeSwKICAgICAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgICAgICBzdHlsZS5mb250X3NpemUsCiAgICAgICAgICAgICAgICApOwogICAgICAgICAgICB9CgogICAgICAgICAgICBpZiBsZXQgU29tZShncmFwaGljKSA9IHJ1bi5zcGFuLm1lZGlhIHsKICAgICAgICAgICAgICAgIGlmICFsYXN0X3JlbmRlcmVkX2dyYXBoaWMuY29udGFpbnMoJmdyYXBoaWMuaWQpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0X3ggPSBncmFwaGljLm9mZnNldF94IGFzIGYzMjsKICAgICAgICAgICAgICAgICAgICBsZXQgb2Zmc2V0X3kgPSBncmFwaGljLm9mZnNldF95IGFzIGYzMjsKCiAgICAgICAgICAgICAgICAgICAgZ3JhcGhpY3MudG9wX2xheWVyLnB1c2goR3JhcGhpY1JlbmRlclJlcXVlc3QgewogICAgICAgICAgICAgICAgICAgICAgICBpZDogZ3JhcGhpYy5pZCwKICAgICAgICAgICAgICAgICAgICAgICAgcG9zX3g6IHJ1bl94IC0gb2Zmc2V0X3gsCiAgICAgICAgICAgICAgICAgICAgICAgIHBvc195OiBzdHlsZS50b3BsaW5lIC0gb2Zmc2V0X3ksCiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBOb25lLAogICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IE5vbmUsCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgbGFzdF9yZW5kZXJlZF9ncmFwaGljLmluc2VydChncmFwaGljLmlkKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29tcC5kcmF3X3J1bigKICAgICAgICAgICAgICAgICZtdXQgc2Vzc2lvbiwKICAgICAgICAgICAgICAgIFJlY3Q6Om5ldyhydW5feCwgcHksIHN0eWxlLmFkdmFuY2UsIDEuKSwKICAgICAgICAgICAgICAgIGRlcHRoLAogICAgICAgICAgICAgICAgJnN0eWxlLAogICAgICAgICAgICAgICAgJmdseXBocywKICAgICAgICAgICAgKTsKICAgICAgICB9CiAgICB9CgogICAgLy8gbGV0IGR1cmF0aW9uID0gc3RhcnQuZWxhcHNlZCgpOwogICAgLy8gcHJpbnRsbiEoIiAtIGRyYXdfbGF5b3V0KCkgaXM6IHs6P31cbiIsIGR1cmF0aW9uKTsKfQoKI1tpbmxpbmVdCmZuIGZldGNoX2RpbWVuc2lvbnMoCiAgICBjb21wOiAmbXV0IGNvbXBvc2l0b3I6OkNvbXBvc2l0b3IsCiAgICBjYWNoZXM6ICgmbXV0IEltYWdlQ2FjaGUsICZtdXQgR2x5cGhDYWNoZSksCiAgICBsaW5lOiAmY3JhdGU6OmxheW91dDo6QnVpbGRlckxpbmUsCiAgICBmb250X2xpYnJhcnk6ICZGb250TGlicmFyeSwKKSAtPiBTdWdhckRpbWVuc2lvbnMgewogICAgbGV0IHggPSAwLjsKICAgIGxldCB5ID0gMC47CgogICAgbGV0IChpbWFnZV9jYWNoZSwgZ2x5cGhzX2NhY2hlKSA9IGNhY2hlczsKICAgIGxldCBtdXQgY3VycmVudF9mb250ID0gMDsKICAgIGxldCBtdXQgY3VycmVudF9mb250X3NpemUgPSAwLjA7CiAgICBsZXQgZm9udF9jb29yZHM6ICZbaTE2XSA9ICZbMCwgMCwgMCwgMF07CiAgICBpZiBsZXQgU29tZShmaXJzdF9ydW4pID0gbGluZS5yZW5kZXJfZGF0YS5ydW5zLmZpcnN0KCkgewogICAgICAgIGN1cnJlbnRfZm9udCA9IGZpcnN0X3J1bi5zcGFuLmZvbnRfaWQ7CiAgICAgICAgY3VycmVudF9mb250X3NpemUgPSBmaXJzdF9ydW4uc2l6ZTsKICAgIH0KCiAgICBsZXQgbXV0IHNlc3Npb24gPSBnbHlwaHNfY2FjaGUuc2Vzc2lvbigKICAgICAgICBpbWFnZV9jYWNoZSwKICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgZm9udF9saWJyYXJ5LAogICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgKTsKCiAgICBsZXQgbXV0IGdseXBocyA9IFZlYzo6d2l0aF9jYXBhY2l0eSgzKTsKICAgIGxldCBtdXQgZGltZW5zaW9uID0gU3VnYXJEaW1lbnNpb25zOjpkZWZhdWx0KCk7CiAgICBsZXQgZmlyc3RfcnVuID0gJmxpbmUucmVuZGVyX2RhdGEucnVuc1swXTsKICAgIGxldCBhc2NlbnQgPSBmaXJzdF9ydW4uYXNjZW50LnJvdW5kKCk7CiAgICBsZXQgZGVzY2VudCA9IGZpcnN0X3J1bi5kZXNjZW50LnJvdW5kKCk7CiAgICBsZXQgbGVhZGluZyA9IChmaXJzdF9ydW4ubGVhZGluZykucm91bmQoKSAqIDIuOwogICAgLy8gbGV0IG11dCBweCA9IHggKyBsaW5lLm9mZnNldCgpOwogICAgbGV0IG11dCBweCA9IHggKyAwLjA7CiAgICBsZXQgcHkgPSBhc2NlbnQgKyB5OwogICAgbGV0IGxpbmVfaGVpZ2h0ID0gYXNjZW50ICsgZGVzY2VudCArIGxlYWRpbmc7CiAgICBmb3IgcnVuIGluICZsaW5lLnJlbmRlcl9kYXRhLnJ1bnMgewogICAgICAgIGxldCBjaGFyX3dpZHRoID0gcnVuLnNwYW4ud2lkdGg7CgogICAgICAgIGxldCBmb250ID0gcnVuLnNwYW4uZm9udF9pZDsKICAgICAgICBsZXQgcnVuX3ggPSBweDsKICAgICAgICBnbHlwaHMuY2xlYXIoKTsKICAgICAgICBmb3IgZ2x5cGggaW4gJnJ1bi5nbHlwaHMgewogICAgICAgICAgICAvLyBsZXQgeCA9IHB4ICsgZ2x5cGgueDsKICAgICAgICAgICAgLy8gbGV0IHkgPSBweSAtIGdseXBoLnk7CiAgICAgICAgICAgIGxldCB4ID0gcHg7CiAgICAgICAgICAgIGxldCB5ID0gcHk7CiAgICAgICAgICAgIC8vIHB4ICs9IGdseXBoLmFkdmFuY2UKICAgICAgICAgICAgcHggKz0gZ2x5cGguc2ltcGxlX2RhdGEoKS4xICogY2hhcl93aWR0aDsKICAgICAgICAgICAgZ2x5cGhzLnB1c2goR2x5cGggewogICAgICAgICAgICAgICAgaWQ6IGdseXBoLnNpbXBsZV9kYXRhKCkuMCwKICAgICAgICAgICAgICAgIHgsCiAgICAgICAgICAgICAgICB5LAogICAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgbGV0IGNvbG9yID0gcnVuLnNwYW4uY29sb3I7CgogICAgICAgIGxldCBzdHlsZSA9IFRleHRSdW5TdHlsZSB7CiAgICAgICAgICAgIGZvbnRfY29vcmRzLAogICAgICAgICAgICBmb250X3NpemU6IHJ1bi5zaXplLAogICAgICAgICAgICBjb2xvciwKICAgICAgICAgICAgY3Vyc29yOiBydW4uc3Bhbi5jdXJzb3IsCiAgICAgICAgICAgIGJhY2tncm91bmRfY29sb3I6IE5vbmUsCiAgICAgICAgICAgIGJhc2VsaW5lOiBweSwKICAgICAgICAgICAgdG9wbGluZTogcHkgLSBhc2NlbnQsCiAgICAgICAgICAgIGxpbmVfaGVpZ2h0LAogICAgICAgICAgICBhZHZhbmNlOiBweCAtIHJ1bl94LAogICAgICAgICAgICBkZWNvcmF0aW9uOiBOb25lLAogICAgICAgICAgICBkZWNvcmF0aW9uX2NvbG9yOiBOb25lLAogICAgICAgIH07CgogICAgICAgIGlmIHN0eWxlLmFkdmFuY2UgPiAwLiAmJiBsaW5lX2hlaWdodCA+IDAuIHsKICAgICAgICAgICAgZGltZW5zaW9uLndpZHRoID0gc3R5bGUuYWR2YW5jZS5yb3VuZCgpOwogICAgICAgICAgICBkaW1lbnNpb24uaGVpZ2h0ID0gbGluZV9oZWlnaHQucm91bmQoKTsKICAgICAgICB9CgogICAgICAgIGlmIGZvbnQgIT0gY3VycmVudF9mb250IHx8IHN0eWxlLmZvbnRfc2l6ZSAhPSBjdXJyZW50X2ZvbnRfc2l6ZSB7CiAgICAgICAgICAgIGN1cnJlbnRfZm9udCA9IGZvbnQ7CiAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplID0gc3R5bGUuZm9udF9zaXplOwoKICAgICAgICAgICAgc2Vzc2lvbiA9IGdseXBoc19jYWNoZS5zZXNzaW9uKAogICAgICAgICAgICAgICAgaW1hZ2VfY2FjaGUsCiAgICAgICAgICAgICAgICBjdXJyZW50X2ZvbnQsCiAgICAgICAgICAgICAgICBmb250X2xpYnJhcnksCiAgICAgICAgICAgICAgICBmb250X2Nvb3JkcywKICAgICAgICAgICAgICAgIGN1cnJlbnRfZm9udF9zaXplLAogICAgICAgICAgICApOwogICAgICAgIH0KCiAgICAgICAgY29tcC5kcmF3X3J1bigKICAgICAgICAgICAgJm11dCBzZXNzaW9uLAogICAgICAgICAgICBSZWN0OjpuZXcocnVuX3gsIHB5LCBzdHlsZS5hZHZhbmNlLCAxLiksCiAgICAgICAgICAgIDAuMCwKICAgICAgICAgICAgJnN0eWxlLAogICAgICAgICAgICAmZ2x5cGhzLAogICAgICAgICk7CiAgICB9CgogICAgZGltZW5zaW9uCn0KCiNbaW5saW5lXQpmbiBuZXh0X2NvcHlfYnVmZmVyX3NpemUoc2l6ZTogdTY0KSAtPiB1NjQgewogICAgbGV0IGFsaWduX21hc2sgPSB3Z3B1OjpDT1BZX0JVRkZFUl9BTElHTk1FTlQgLSAxOwogICAgKChzaXplLm5leHRfcG93ZXJfb2ZfdHdvKCkgKyBhbGlnbl9tYXNrKSAmICFhbGlnbl9tYXNrKQogICAgICAgIC5tYXgod2dwdTo6Q09QWV9CVUZGRVJfQUxJR05NRU5UKQp9CgAAAAAAAAAAU1YAAAAAAAAAAAAAAAAAAAAAAABTVgAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADcQQAAAAAAANxBAAAAAAAAAAAAAAAA8L8" - ] - ] - }, - { - "file": "/Users/rapha/Documents/a/rio/pkgRio.nix", - "settings": - { - "buffer_size": 2578, - "encoding": "UTF-8", - "line_ending": "Unix" - }, - "undo_stack": - [ - [ - 4, - 1, - "cut", - null, - "AQAAAEkFAAAAAAAASQUAAAAAAAAVAAAAICAgIGRvQ2hlY2sgPSBmYWxzZTsK", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABdBQAAAAAAAF0FAAAAAAAAAAAAAAAA8L8" - ], - [ - 5, - 1, - "left_delete", - null, - "AQAAAEgFAAAAAAAASAUAAAAAAAABAAAACg", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABJBQAAAAAAAEkFAAAAAAAAAAAAAAAA8L8" - ] - ] - }, - { - "contents": "use raw_window_handle::{HasDisplayHandle, HasWindowHandle};\nuse rio_window::application::ApplicationHandler;\nuse rio_window::event_loop::ControlFlow;\nuse rio_window::event_loop::{ActiveEventLoop, DeviceEvents};\nuse rio_window::window::{Window, WindowId};\nuse rio_window::{\n dpi::LogicalSize, event::WindowEvent, event_loop::EventLoop, window::WindowAttributes,\n};\nuse std::error::Error;\nuse sugarloaf::{\n layout::RootStyle, FragmentStyle, FragmentStyleDecoration, Object, RichText,\n Sugarloaf, SugarCursor, SugarloafWindow, SugarloafWindowSize, UnderlineInfo, UnderlineShape,\n};\n\nfn main() {\n let width = 600.0;\n let height = 400.0;\n let window_event_loop = rio_window::event_loop::EventLoop::new().unwrap();\n let mut application = Application::new(&window_event_loop, width, height);\n let _ = application.run(window_event_loop);\n}\n\nstruct Application {\n sugarloaf: Option>,\n window: Option,\n height: f32,\n width: f32,\n}\n\nimpl Application {\n fn new(event_loop: &EventLoop<()>, width: f32, height: f32) -> Self {\n event_loop.listen_device_events(DeviceEvents::Never);\n\n Application {\n sugarloaf: None,\n window: None,\n width,\n height,\n }\n }\n\n fn run(&mut self, event_loop: EventLoop<()>) -> Result<(), Box> {\n let result = event_loop.run_app(self);\n result.map_err(Into::into)\n }\n}\n\nimpl ApplicationHandler for Application {\n fn resumed(&mut self, active_event_loop: &ActiveEventLoop) {\n let window_attribute = WindowAttributes::default()\n .with_title(\"Line height example\")\n .with_inner_size(LogicalSize::new(self.width, self.height))\n .with_resizable(true);\n let window = active_event_loop.create_window(window_attribute).unwrap();\n\n let scale_factor = window.scale_factor();\n let font_size = 24.;\n\n let line_height = 2.0;\n let sugarloaf_layout =\n RootStyle::new(scale_factor as f32, font_size, line_height);\n\n let size = window.inner_size();\n let sugarloaf_window = SugarloafWindow {\n handle: window.window_handle().unwrap().into(),\n display: window.display_handle().unwrap().into(),\n scale: scale_factor as f32,\n size: SugarloafWindowSize {\n width: size.width as f32,\n height: size.height as f32,\n },\n };\n\n let mut sugarloaf = Sugarloaf::new(\n sugarloaf_window,\n sugarloaf::SugarloafRenderer::default(),\n &sugarloaf::font::FontLibrary::default(),\n sugarloaf_layout,\n )\n .expect(\"Sugarloaf instance should be created\");\n\n sugarloaf.set_background_color(Some(wgpu::Color::RED));\n sugarloaf.create_rich_text();\n window.request_redraw();\n\n self.sugarloaf = Some(sugarloaf);\n self.window = Some(window);\n }\n\n fn window_event(\n &mut self,\n event_loop: &ActiveEventLoop,\n _window_id: WindowId,\n event: WindowEvent,\n ) {\n if self.sugarloaf.is_none() || self.window.is_none() {\n return;\n }\n\n let sugarloaf = self.sugarloaf.as_mut().unwrap();\n let window = self.window.as_mut().unwrap();\n\n match event {\n WindowEvent::CloseRequested => event_loop.exit(),\n WindowEvent::ScaleFactorChanged {\n // mut inner_size_writer,\n scale_factor,\n ..\n } => {\n let scale_factor_f32 = scale_factor as f32;\n let new_inner_size = window.inner_size();\n sugarloaf.rescale(scale_factor_f32);\n sugarloaf.resize(new_inner_size.width, new_inner_size.height);\n window.request_redraw();\n }\n WindowEvent::Resized(new_size) => {\n sugarloaf.resize(new_size.width, new_size.height);\n window.request_redraw();\n }\n WindowEvent::RedrawRequested { .. } => {\n let content = sugarloaf.content();\n content.sel(0).clear();\n content\n .new_line()\n .add_text(\n \"Sugarloaf\",\n FragmentStyle {\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .new_line()\n .add_text(\n \"│㏑¼\",\n FragmentStyle {\n color: [0.0, 0.0, 0.0, 1.0],\n background_color: Some([1.0, 1.0, 1.0, 1.0]),\n width: 2.0,\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"🥶\",\n FragmentStyle {\n color: [1.0, 0.0, 1.0, 1.0],\n background_color: Some([0.3, 0.5, 1.0, 1.0]),\n width: 2.0,\n ..FragmentStyle::default()\n },\n )\n .new_line()\n .add_text(\n \"│regular -> \",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Regular,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \" \",\n FragmentStyle {\n decoration: None,\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"|still|\",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Regular,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \" \",\n FragmentStyle {\n decoration: None,\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"│curly\",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Curly,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .new_line()\n .add_text(\n \"│dashed\",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Dashed,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \" \",\n FragmentStyle {\n decoration: None,\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"dotted\",\n FragmentStyle {\n decoration: Some(FragmentStyleDecoration::Underline(\n UnderlineInfo {\n offset: -2.0,\n size: 1.0,\n is_doubled: false,\n shape: UnderlineShape::Dotted,\n },\n )),\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.0, 0.0, 0.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .new_line()\n .add_text(\n \"│ \\u{E0B6}Hello There!\\u{e0b4}\",\n FragmentStyle {\n color: [1.0, 1.0, 1.0, 1.0],\n background_color: Some([0.5, 0.5, 1.0, 1.0]),\n ..FragmentStyle::default()\n },\n )\n .add_text(\n \"?\",\n FragmentStyle {\n color: [0.5, 0.5, 1.0, 1.0],\n background_color: Some([1.0, 1.0, 1.0, 1.0]),\n cursor: Some(SugarCursor::Block([1.0, 1.0, 1.0, 1.0])),\n ..FragmentStyle::default()\n },\n )\n .build();\n\n sugarloaf.set_objects(vec![Object::RichText(RichText {\n id: 0,\n position: [10., 0.],\n })]);\n sugarloaf.render();\n event_loop.set_control_flow(ControlFlow::Wait);\n }\n _ => (),\n }\n }\n}\n", - "file": "/Users/rapha/Documents/a/rio/sugarloaf/examples/line_height.rs", - "file_size": 11526, - "file_write_time": 133789560807006437, - "settings": - { - "buffer_size": 11510, - "line_ending": "Unix" - }, - "undo_stack": - [ - [ - 5, - 1, - "insert", - { - "characters": "\n" - }, - "AgAAAOwpAAAAAAAA7SkAAAAAAAAAAAAA7SkAAAAAAAABKgAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADsKQAAAAAAAOwpAAAAAAAAAAAAAAAA8L8" - ], - [ - 6, - 1, - "paste", - null, - "AQAAAAEqAAAAAAAAWCsAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAABKgAAAAAAAAEqAAAAAAAAAAAAAAAA8L8" - ], - [ - 11, - 1, - "left_delete", - null, - "AQAAACUqAAAAAAAAJSoAAAAAAAAgAAAA4pSCIFx1e0UwQjZ9SGVsbG8gVGhlcmUhXHV7ZTBiNH0", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlKgAAAAAAAEMqAAAAAAAAAAAAAAAA8L8" - ], - [ - 12, - 1, - "insert", - { - "characters": "?" - }, - "AQAAACUqAAAAAAAAJioAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlKgAAAAAAACUqAAAAAAAAAAAAAAAA8L8" - ], - [ - 24, - 1, - "paste", - null, - "AQAAAL0qAAAAAAAA0ioAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAC9KgAAAAAAAL0qAAAAAAAAAAAAAAAA8L8" - ], - [ - 34, - 1, - "left_delete", - null, - "AQAAANIqAAAAAAAA0ioAAAAAAAAUAAAAWzAuNSwgMC41LCAxLjAsIDEuMF0", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADSKgAAAAAAAOYqAAAAAAAAAAAAAAAA8L8" - ], - [ - 40, - 1, - "left_delete", - null, - "AQAAAHQqAAAAAAAAdCoAAAAAAAAUAAAAWzEuMCwgMS4wLCAxLjAsIDEuMF0", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACIKgAAAAAAAHQqAAAAAAAAAAAAAAAA8L8" - ], - [ - 41, - 1, - "paste", - null, - "AQAAAHQqAAAAAAAAiCoAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB0KgAAAAAAAHQqAAAAAAAAAAAAAAAA8L8" - ], - [ - 45, - 1, - "insert", - { - "characters": "\ncu" - }, - "BAAAANQqAAAAAAAA1SoAAAAAAAAAAAAA1SoAAAAAAADxKgAAAAAAAAAAAADxKgAAAAAAAPIqAAAAAAAAAAAAAPIqAAAAAAAA8yoAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADUKgAAAAAAANQqAAAAAAAA////////738" - ], - [ - 46, - 2, - "left_delete", - null, - "AgAAAPIqAAAAAAAA8ioAAAAAAAABAAAAdfEqAAAAAAAA8SoAAAAAAAABAAAAYw", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADzKgAAAAAAAPMqAAAAAAAAAAAAAAAA8L8" - ], - [ - 52, - 1, - "paste", - null, - "AQAAAPEqAAAAAAAAdCwAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADxKgAAAAAAAPEqAAAAAAAAAAAAAAAA8L8" - ], - [ - 64, - 2, - "left_delete", - null, - "AgAAAPIqAAAAAAAA8ioAAAAAAAAKAAAAZGVjb3JhdGlvbvEqAAAAAAAA8SoAAAAAAAABAAAAIA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADyKgAAAAAAAPwqAAAAAAAAAAAAAAAA8L8" - ], - [ - 65, - 1, - "insert", - { - "characters": "cursor" - }, - "BgAAAPEqAAAAAAAA8ioAAAAAAAAAAAAA8ioAAAAAAADzKgAAAAAAAAAAAADzKgAAAAAAAPQqAAAAAAAAAAAAAPQqAAAAAAAA9SoAAAAAAAAAAAAA9SoAAAAAAAD2KgAAAAAAAAAAAAD2KgAAAAAAAPcqAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADxKgAAAAAAAPEqAAAAAAAAAAAAAAAA8L8" - ], - [ - 69, - 1, - "left_delete", - null, - "AQAAAP4qAAAAAAAA/ioAAAAAAAAXAAAARnJhZ21lbnRTdHlsZURlY29yYXRpb24", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAD+KgAAAAAAABUrAAAAAAAAAAAAAAAA8L8" - ], - [ - 70, - 1, - "paste", - null, - "AQAAAP4qAAAAAAAACSsAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAD+KgAAAAAAAP4qAAAAAAAAAAAAAAAA8L8" - ], - [ - 73, - 1, - "left_delete", - null, - "AQAAAAsrAAAAAAAACysAAAAAAAAJAAAAVW5kZXJsaW5l", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAUKwAAAAAAAAsrAAAAAAAAAAAAAAAA8L8" - ], - [ - 74, - 1, - "insert", - { - "characters": "Block" - }, - "BQAAAAsrAAAAAAAADCsAAAAAAAAAAAAADCsAAAAAAAANKwAAAAAAAAAAAAANKwAAAAAAAA4rAAAAAAAAAAAAAA4rAAAAAAAADysAAAAAAAAAAAAADysAAAAAAAAQKwAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAALKwAAAAAAAAsrAAAAAAAAAAAAAAAA8L8" - ], - [ - 84, - 1, - "paste", - null, - "AQAAABErAAAAAAAAJSsAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAARKwAAAAAAABErAAAAAAAAAAAAAAAIiEA" - ], - [ - 85, - 1, - "insert", - { - "characters": ")," - }, - "AgAAACUrAAAAAAAAJisAAAAAAAAAAAAAJisAAAAAAAAnKwAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlKwAAAAAAACUrAAAAAAAAAAAAAAAA8L8" - ], - [ - 87, - 7, - "cut", - null, - "BwAAACgrAAAAAAAAKCsAAAAAAAAwAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBVbmRlcmxpbmVJbmZvIHsKKCsAAAAAAAAoKwAAAAAAADIAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXQ6IC0yLjAsCigrAAAAAAAAKCsAAAAAAAAvAAAAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogMS4wLAooKwAAAAAAACgrAAAAAAAANwAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzX2RvdWJsZWQ6IGZhbHNlLAooKwAAAAAAACgrAAAAAAAAQwAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlOiBVbmRlcmxpbmVTaGFwZTo6RG90dGVkLAooKwAAAAAAACgrAAAAAAAAIwAAACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSwKKCsAAAAAAAAoKwAAAAAAACAAAAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSksCg", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABXKwAAAAAAAFcrAAAAAAAAAAAAAADIi0A" - ], - [ - 91, - 1, - "left_delete", - null, - "AQAAANEqAAAAAAAA0SoAAAAAAAABAAAALA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADSKgAAAAAAANIqAAAAAAAAAAAAAAAA8L8" - ], - [ - 95, - 1, - "insert", - { - "characters": ")" - }, - "AQAAACUrAAAAAAAAJisAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAAlKwAAAAAAACUrAAAAAAAAAAAAAAAA8L8" - ], - [ - 103, - 1, - "insert", - { - "characters": " Sug" - }, - "BAAAAPYBAAAAAAAA9wEAAAAAAAAAAAAA9wEAAAAAAAD4AQAAAAAAAAAAAAD4AQAAAAAAAPkBAAAAAAAAAAAAAPkBAAAAAAAA+gEAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAD2AQAAAAAAAPYBAAAAAAAAAAAAAAAA8L8" - ], - [ - 106, - 1, - "insert_completion", - { - "completion": "SugarCursor", - "format": "text", - "keep_prefix": false, - "must_insert": false, - "trigger": "SugarCursor" - }, - "AgAAAPcBAAAAAAAA9wEAAAAAAAADAAAAU3Vn9wEAAAAAAAACAgAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAD6AQAAAAAAAPoBAAAAAAAAAAAAAAAA8L8" - ], - [ - 107, - 1, - "insert", - { - "characters": "," - }, - "AQAAAAICAAAAAAAAAwIAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAACAgAAAAAAAAICAAAAAAAAAAAAAAAA8L8" - ] - ] - }, - { - "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/content.rs", - "settings": - { - "buffer_size": 19461, - "line_ending": "Unix" - }, - "undo_stack": - [ - [ - 15, - 1, - "insert", - { - "characters": " *" - }, - "AgAAAGUjAAAAAAAAZiMAAAAAAAAAAAAAZiMAAAAAAABnIwAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABlIwAAAAAAAGUjAAAAAAAAAAAAAAAA8L8" - ], - [ - 16, - 1, - "insert", - { - "characters": " " - }, - "AQAAAGcjAAAAAAAAaCMAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABnIwAAAAAAAGcjAAAAAAAAAAAAAAAA8L8" - ], - [ - 17, - 1, - "paste", - null, - "AQAAAGgjAAAAAAAAciMAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABoIwAAAAAAAGgjAAAAAAAAAAAAAAAA8L8" - ], - [ - 18, - 1, - "insert", - { - "characters": ".di" - }, - "AwAAAHIjAAAAAAAAcyMAAAAAAAAAAAAAcyMAAAAAAAB0IwAAAAAAAAAAAAB0IwAAAAAAAHUjAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAByIwAAAAAAAHIjAAAAAAAAAAAAAAAA8L8" - ], - [ - 19, - 1, - "insert_completion", - { - "completion": "dimensions", - "format": "text", - "keep_prefix": false, - "must_insert": false, - "trigger": "dimensions" - }, - "AgAAAHMjAAAAAAAAcyMAAAAAAAACAAAAZGlzIwAAAAAAAH0jAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB1IwAAAAAAAHUjAAAAAAAAAAAAAAAA8L8" - ], - [ - 20, - 1, - "insert", - { - "characters": ".line" - }, - "BQAAAH0jAAAAAAAAfiMAAAAAAAAAAAAAfiMAAAAAAAB/IwAAAAAAAAAAAAB/IwAAAAAAAIAjAAAAAAAAAAAAAIAjAAAAAAAAgSMAAAAAAAAAAAAAgSMAAAAAAACCIwAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB9IwAAAAAAAH0jAAAAAAAAAAAAAAAA8L8" - ], - [ - 23, - 1, - "insert_completion", - { - "completion": "line_height", - "format": "text", - "keep_prefix": false, - "must_insert": false, - "trigger": "line_height" - }, - "AgAAAH4jAAAAAAAAfiMAAAAAAAAEAAAAbGluZX4jAAAAAAAAiSMAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACCIwAAAAAAAIIjAAAAAAAAAAAAAAAA8L8" - ], - [ - 26, - 1, - "left_delete", - null, - "AQAAAHMjAAAAAAAAcyMAAAAAAAALAAAAZGltZW5zaW9ucy4", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAB+IwAAAAAAAHMjAAAAAAAAAAAAAAAA8L8" - ], - [ - 43, - 1, - "revert", - null, - "AwAAAAAAAAAAAAAAAAAAAAAAAAAeTAAALy8gQ29weXJpZ2h0IChjKSAyMDIzLXByZXNlbnQsIFJhcGhhZWwgQW1vcmltLgovLwovLyBUaGlzIHNvdXJjZSBjb2RlIGlzIGxpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZSBmb3VuZCBpbiB0aGUKLy8gTElDRU5TRSBmaWxlIGluIHRoZSByb290IGRpcmVjdG9yeSBvZiB0aGlzIHNvdXJjZSB0cmVlLgoKdXNlIGNyYXRlOjpjb21wb25lbnRzOjpyaWNoX3RleHQ6OlJpY2hUZXh0QnJ1c2g7CnVzZSBjcmF0ZTo6Zm9udDo6Rm9udExpYnJhcnk7CnVzZSBjcmF0ZTo6Zm9udF9pbnRyb3NwZWN0b3I6OnNoYXBlOjpjbHVzdGVyOjpHbHlwaENsdXN0ZXI7CnVzZSBjcmF0ZTo6Zm9udF9pbnRyb3NwZWN0b3I6OnNoYXBlOjpjbHVzdGVyOjpPd25lZEdseXBoQ2x1c3RlcjsKdXNlIGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6c2hhcGU6OlNoYXBlQ29udGV4dDsKdXNlIGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6dGV4dDo6U2NyaXB0Owp1c2UgY3JhdGU6OmZvbnRfaW50cm9zcGVjdG9yOjpNZXRyaWNzOwp1c2UgY3JhdGU6OmxheW91dDo6cmVuZGVyX2RhdGE6OlJlbmRlckRhdGE7CnVzZSBjcmF0ZTo6bGF5b3V0OjpSaWNoVGV4dExheW91dDsKdXNlIGxydTo6THJ1Q2FjaGU7CnVzZSBydXN0Y19oYXNoOjpGeEhhc2hNYXA7CnVzZSBzdGQ6Om51bTo6Tm9uWmVyb1VzaXplOwoKdXNlIGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6QXR0cmlidXRlczsKdXNlIGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6U2V0dGluZzsKdXNlIGNyYXRlOjp7c3VnYXJsb2FmOjpwcmltaXRpdmVzOjpTdWdhckN1cnNvciwgR3JhcGhpY307CgovLy8gRGF0YSB0aGF0IGRlc2NyaWJlcyBhIGZyYWdtZW50LgojW2Rlcml2ZShEZWJ1ZywgQ2xvbmUpXQpwdWIgc3RydWN0IEZyYWdtZW50RGF0YSB7CiAgICBwdWIgY29udGVudDogU3RyaW5nLAogICAgLy8vIFN0eWxlCiAgICBwdWIgc3R5bGU6IEZyYWdtZW50U3R5bGUsCn0KCiNbZGVyaXZlKERlZmF1bHQsIENsb25lKV0KcHViIHN0cnVjdCBCdWlsZGVyTGluZSB7CiAgICAvLy8gQ29sbGVjdGlvbiBvZiBmcmFnbWVudHMuCiAgICBwdWIgZnJhZ21lbnRzOiBWZWM8RnJhZ21lbnREYXRhPiwKICAgIHB1YiByZW5kZXJfZGF0YTogUmVuZGVyRGF0YSwKfQoKLy8vIEJ1aWxkZXIgc3RhdGUuCiNbZGVyaXZlKERlZmF1bHQpXQpwdWIgc3RydWN0IEJ1aWxkZXJTdGF0ZSB7CiAgICAvLy8gTGluZXMgU3RhdGUKICAgIHB1YiBsaW5lczogVmVjPEJ1aWxkZXJMaW5lPiwKICAgIC8vLyBGb250IHZhcmlhdGlvbiBzZXR0aW5nIGNhY2hlLgogICAgcHViIHZhcnM6IEZvbnRTZXR0aW5nQ2FjaGU8ZjMyPiwKICAgIG1ldHJpY3NfY2FjaGU6IE1ldHJpY3NDYWNoZSwKICAgIHNjYWxlZF9mb250X3NpemU6IGYzMiwKICAgIHB1YiBsYXlvdXQ6IFJpY2hUZXh0TGF5b3V0LAp9CgppbXBsIEJ1aWxkZXJTdGF0ZSB7CiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBmcm9tX2xheW91dChsYXlvdXQ6ICZSaWNoVGV4dExheW91dCkgLT4gU2VsZiB7CiAgICAgICAgU2VsZiB7CiAgICAgICAgICAgIGxheW91dDogKmxheW91dCwKICAgICAgICAgICAgc2NhbGVkX2ZvbnRfc2l6ZTogbGF5b3V0LmZvbnRfc2l6ZSAqIGxheW91dC5kaW1lbnNpb25zLnNjYWxlLAogICAgICAgICAgICAuLkJ1aWxkZXJTdGF0ZTo6ZGVmYXVsdCgpCiAgICAgICAgfQogICAgfQogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gbmV3X2xpbmUoJm11dCBzZWxmKSB7CiAgICAgICAgc2VsZi5saW5lcy5wdXNoKEJ1aWxkZXJMaW5lOjpkZWZhdWx0KCkpOwogICAgfQogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gY3VycmVudF9saW5lKCZzZWxmKSAtPiB1c2l6ZSB7CiAgICAgICAgc2VsZi5saW5lcy5sZW4oKS53cmFwcGluZ19zdWIoMSkKICAgIH0KICAgICNbaW5saW5lXQogICAgcHViIGZuIGNsZWFyKCZtdXQgc2VsZikgewogICAgICAgIHNlbGYubGluZXMuY2xlYXIoKTsKICAgICAgICBzZWxmLnZhcnMuY2xlYXIoKTsKICAgIH0KICAgICNbaW5saW5lXQogICAgcHViIGZuIHJlc2NhbGUoJm11dCBzZWxmLCBzY2FsZV9mYWN0b3I6IGYzMikgewogICAgICAgIHNlbGYubWV0cmljc19jYWNoZS5pbm5lci5jbGVhcigpOwogICAgICAgIHNlbGYuc2NhbGVkX2ZvbnRfc2l6ZSA9IHNlbGYubGF5b3V0LmZvbnRfc2l6ZSAqIHNjYWxlX2ZhY3RvcjsKICAgICAgICBzZWxmLmxheW91dC5yZXNjYWxlKHNjYWxlX2ZhY3Rvcik7CiAgICB9CiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBiZWdpbigmbXV0IHNlbGYpIHsKICAgICAgICBzZWxmLmxpbmVzLnB1c2goQnVpbGRlckxpbmU6OmRlZmF1bHQoKSk7CiAgICB9CiAgICAjW2lubGluZV0KICAgIHB1YiBmbiB1cGRhdGVfZm9udF9zaXplKCZtdXQgc2VsZikgewogICAgICAgIGxldCBmb250X3NpemUgPSBzZWxmLmxheW91dC5mb250X3NpemU7CiAgICAgICAgbGV0IHNjYWxlID0gc2VsZi5sYXlvdXQuZGltZW5zaW9ucy5zY2FsZTsKICAgICAgICBsZXQgcHJldl9mb250X3NpemUgPSBzZWxmLnNjYWxlZF9mb250X3NpemU7CiAgICAgICAgc2VsZi5zY2FsZWRfZm9udF9zaXplID0gZm9udF9zaXplICogc2NhbGU7CgogICAgICAgIGlmIHByZXZfZm9udF9zaXplICE9IHNlbGYuc2NhbGVkX2ZvbnRfc2l6ZSB7CiAgICAgICAgICAgIHNlbGYubWV0cmljc19jYWNoZS5pbm5lci5jbGVhcigpOwogICAgICAgIH0KICAgIH0KCiAgICBwdWIgZm4gaW5jcmVhc2VfZm9udF9zaXplKCZtdXQgc2VsZikgLT4gYm9vbCB7CiAgICAgICAgaWYgc2VsZi5sYXlvdXQuZm9udF9zaXplIDwgNDAuMCB7CiAgICAgICAgICAgIHNlbGYubGF5b3V0LmZvbnRfc2l6ZSArPSAxLjA7CiAgICAgICAgICAgIHNlbGYudXBkYXRlX2ZvbnRfc2l6ZSgpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgZmFsc2UKICAgIH0KCiAgICBwdWIgZm4gZGVjcmVhc2VfZm9udF9zaXplKCZtdXQgc2VsZikgLT4gYm9vbCB7CiAgICAgICAgaWYgc2VsZi5sYXlvdXQuZm9udF9zaXplID4gNi4wIHsKICAgICAgICAgICAgc2VsZi5sYXlvdXQuZm9udF9zaXplIC09IDEuMDsKICAgICAgICAgICAgc2VsZi51cGRhdGVfZm9udF9zaXplKCk7CiAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgIH0KICAgICAgICBmYWxzZQogICAgfQoKICAgIHB1YiBmbiByZXNldF9mb250X3NpemUoJm11dCBzZWxmKSAtPiBib29sIHsKICAgICAgICBpZiBzZWxmLmxheW91dC5mb250X3NpemUgIT0gc2VsZi5sYXlvdXQub3JpZ2luYWxfZm9udF9zaXplIHsKICAgICAgICAgICAgc2VsZi5sYXlvdXQuZm9udF9zaXplID0gc2VsZi5sYXlvdXQub3JpZ2luYWxfZm9udF9zaXplOwogICAgICAgICAgICBzZWxmLnVwZGF0ZV9mb250X3NpemUoKTsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGZhbHNlCiAgICB9Cn0KCi8vLyBJbmRleCBpbnRvIGEgZm9udCBzZXR0aW5nIGNhY2hlLgpwdWIgdHlwZSBGb250U2V0dGluZ0tleSA9IHUzMjsKCi8vLyBDYWNoZSBvZiB0YWcvdmFsdWUgcGFpcnMgZm9yIGZvbnQgc2V0dGluZ3MuCiNbZGVyaXZlKERlZmF1bHQpXQpwdWIgc3RydWN0IEZvbnRTZXR0aW5nQ2FjaGU8VDogQ29weSArIFBhcnRpYWxPcmQgKyBQYXJ0aWFsRXE+IHsKICAgIHNldHRpbmdzOiBWZWM8U2V0dGluZzxUPj4sCiAgICBsaXN0czogVmVjPEZvbnRTZXR0aW5nTGlzdD4sCiAgICB0bXA6IFZlYzxTZXR0aW5nPFQ+PiwKfQoKaW1wbDxUOiBDb3B5ICsgUGFydGlhbE9yZCArIFBhcnRpYWxFcT4gRm9udFNldHRpbmdDYWNoZTxUPiB7CiAgICBwdWIgZm4gZ2V0KCZzZWxmLCBrZXk6IHUzMikgLT4gJltTZXR0aW5nPFQ+XSB7CiAgICAgICAgaWYga2V5ID09ICEwIHsKICAgICAgICAgICAgJltdCiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc2VsZi5saXN0cwogICAgICAgICAgICAgICAgLmdldChrZXkgYXMgdXNpemUpCiAgICAgICAgICAgICAgICAubWFwKHxsaXN0fCBsaXN0LmdldCgmc2VsZi5zZXR0aW5ncykpCiAgICAgICAgICAgICAgICAudW53cmFwX29yKCZbXSkKICAgICAgICB9CiAgICB9CgogICAgcHViIGZuIGNsZWFyKCZtdXQgc2VsZikgewogICAgICAgIHNlbGYuc2V0dGluZ3MuY2xlYXIoKTsKICAgICAgICBzZWxmLmxpc3RzLmNsZWFyKCk7CiAgICAgICAgc2VsZi50bXAuY2xlYXIoKTsKICAgIH0KfQoKLy8vIFNlbnRpbmVsIGZvciBhbiBlbXB0eSBzZXQgb2YgZm9udCBzZXR0aW5ncy4KcHViIGNvbnN0IEVNUFRZX0ZPTlRfU0VUVElOR1M6IEZvbnRTZXR0aW5nS2V5ID0gITA7CgovLy8gUmFuZ2Ugd2l0aGluIGEgZm9udCBzZXR0aW5nIGNhY2hlLgojW2Rlcml2ZShDb3B5LCBDbG9uZSldCnN0cnVjdCBGb250U2V0dGluZ0xpc3QgewogICAgcHViIHN0YXJ0OiB1MzIsCiAgICBwdWIgZW5kOiB1MzIsCn0KCmltcGwgRm9udFNldHRpbmdMaXN0IHsKICAgIHB1YiBmbiBnZXQ8VD4oc2VsZiwgZWxlbWVudHM6ICZbVF0pIC0+ICZbVF0gewogICAgICAgIGVsZW1lbnRzCiAgICAgICAgICAgIC5nZXQoc2VsZi5zdGFydCBhcyB1c2l6ZS4uc2VsZi5lbmQgYXMgdXNpemUpCiAgICAgICAgICAgIC51bndyYXBfb3IoJltdKQogICAgfQp9CgojW3JlcHIodTgpXQojW2Rlcml2ZShDb3B5LCBDbG9uZSwgUGFydGlhbEVxLCBEZWJ1ZywgRGVmYXVsdCldCnB1YiBlbnVtIFVuZGVybGluZVNoYXBlIHsKICAgICNbZGVmYXVsdF0KICAgIFJlZ3VsYXIgPSAwLAogICAgRG90dGVkID0gMSwKICAgIERhc2hlZCA9IDIsCiAgICBDdXJseSA9IDMsCn0KCiNbZGVyaXZlKENvcHksIENsb25lLCBQYXJ0aWFsRXEsIERlYnVnKV0KcHViIHN0cnVjdCBVbmRlcmxpbmVJbmZvIHsKICAgIHB1YiBvZmZzZXQ6IGYzMiwKICAgIHB1YiBzaXplOiBmMzIsCiAgICBwdWIgaXNfZG91YmxlZDogYm9vbCwKICAgIHB1YiBzaGFwZTogVW5kZXJsaW5lU2hhcGUsCn0KCiNbZGVyaXZlKENvcHksIENsb25lLCBQYXJ0aWFsRXEsIERlYnVnKV0KcHViIGVudW0gRnJhZ21lbnRTdHlsZURlY29yYXRpb24gewogICAgLy8gb2Zmc2V0LCBzaXplCiAgICBVbmRlcmxpbmUoVW5kZXJsaW5lSW5mbyksCiAgICBTdHJpa2V0aHJvdWdoLAp9CgojW2Rlcml2ZShDb3B5LCBDbG9uZSwgUGFydGlhbEVxLCBEZWJ1ZyldCnB1YiBzdHJ1Y3QgRnJhZ21lbnRTdHlsZSB7CiAgICBwdWIgZm9udF9pZDogdXNpemUsCiAgICAvLyAgVW5pY29kZSB3aWR0aAogICAgcHViIHdpZHRoOiBmMzIsCiAgICAvLy8gRm9udCBhdHRyaWJ1dGVzLgogICAgcHViIGZvbnRfYXR0cnM6IEF0dHJpYnV0ZXMsCiAgICAvLy8gRm9udCBjb2xvci4KICAgIHB1YiBjb2xvcjogW2YzMjsgNF0sCiAgICAvLy8gQmFja2dyb3VuZCBjb2xvci4KICAgIHB1YiBiYWNrZ3JvdW5kX2NvbG9yOiBPcHRpb248W2YzMjsgNF0+LAogICAgLy8vIEZvbnQgdmFyaWF0aW9ucy4KICAgIHB1YiBmb250X3ZhcnM6IEZvbnRTZXR0aW5nS2V5LAogICAgLy8vIEFkZGl0aW9uYWwgc3BhY2luZyBiZXR3ZWVuIGxldHRlcnMgKGNsdXN0ZXJzKSBvZiB0ZXh0LgogICAgLy8gcHViIGxldHRlcl9zcGFjaW5nOiBmMzIsCiAgICAvLy8gQWRkaXRpb25hbCBzcGFjaW5nIGJldHdlZW4gd29yZHMgb2YgdGV4dC4KICAgIC8vIHB1YiB3b3JkX3NwYWNpbmc6IGYzMiwKICAgIC8vLyBNdWx0aXBsaWNhdGl2ZSBsaW5lIHNwYWNpbmcgZmFjdG9yLgogICAgLy8gcHViIGxpbmVfc3BhY2luZzogZjMyLAogICAgLy8vIEVuYWJsZSB1bmRlcmxpbmUgZGVjb3JhdGlvbi4KICAgIHB1YiBkZWNvcmF0aW9uOiBPcHRpb248RnJhZ21lbnRTdHlsZURlY29yYXRpb24+LAogICAgLy8vIERlY29yYXRpb24gY29sb3IuCiAgICBwdWIgZGVjb3JhdGlvbl9jb2xvcjogT3B0aW9uPFtmMzI7IDRdPiwKICAgIC8vLyBDdXJzb3Igc3R5bGUuCiAgICBwdWIgY3Vyc29yOiBPcHRpb248U3VnYXJDdXJzb3I+LAogICAgLy8vIE1lZGlhCiAgICBwdWIgbWVkaWE6IE9wdGlvbjxHcmFwaGljPiwKfQoKaW1wbCBEZWZhdWx0IGZvciBGcmFnbWVudFN0eWxlIHsKICAgIGZuIGRlZmF1bHQoKSAtPiBTZWxmIHsKICAgICAgICBTZWxmIHsKICAgICAgICAgICAgZm9udF9pZDogMCwKICAgICAgICAgICAgd2lkdGg6IDEuMCwKICAgICAgICAgICAgZm9udF9hdHRyczogQXR0cmlidXRlczo6ZGVmYXVsdCgpLAogICAgICAgICAgICBmb250X3ZhcnM6IEVNUFRZX0ZPTlRfU0VUVElOR1MsCiAgICAgICAgICAgIC8vIGxldHRlcl9zcGFjaW5nOiAwLiwKICAgICAgICAgICAgLy8gd29yZF9zcGFjaW5nOiAwLiwKICAgICAgICAgICAgLy8gbGluZV9zcGFjaW5nOiAxLiwKICAgICAgICAgICAgY29sb3I6IFsxLjAsIDEuMCwgMS4wLCAxLjBdLAogICAgICAgICAgICBiYWNrZ3JvdW5kX2NvbG9yOiBOb25lLAogICAgICAgICAgICBjdXJzb3I6IE5vbmUsCiAgICAgICAgICAgIGRlY29yYXRpb246IE5vbmUsCiAgICAgICAgICAgIGRlY29yYXRpb25fY29sb3I6IE5vbmUsCiAgICAgICAgICAgIG1lZGlhOiBOb25lLAogICAgICAgIH0KICAgIH0KfQoKLy8vIENvbnRleHQgZm9yIHBhcmFncmFwaCBsYXlvdXQuCnB1YiBzdHJ1Y3QgQ29udGVudCB7CiAgICBmb250czogRm9udExpYnJhcnksCiAgICBmb250X2ZlYXR1cmVzOiBWZWM8Y3JhdGU6OmZvbnRfaW50cm9zcGVjdG9yOjpTZXR0aW5nPHUxNj4+LAogICAgc2N4OiBTaGFwZUNvbnRleHQsCiAgICBwdWIgc3RhdGVzOiBGeEhhc2hNYXA8dXNpemUsIEJ1aWxkZXJTdGF0ZT4sCiAgICB3b3JkX2NhY2hlOiBXb3JkQ2FjaGUsCiAgICBzZWxlY3RvcjogT3B0aW9uPHVzaXplPiwKfQoKaW1wbCBDb250ZW50IHsKICAgIC8vLyBDcmVhdGVzIGEgbmV3IGxheW91dCBjb250ZXh0IHdpdGggdGhlIHNwZWNpZmllZCBmb250IGxpYnJhcnkuCiAgICBwdWIgZm4gbmV3KGZvbnRfbGlicmFyeTogJkZvbnRMaWJyYXJ5KSAtPiBTZWxmIHsKICAgICAgICBTZWxmIHsKICAgICAgICAgICAgZm9udHM6IGZvbnRfbGlicmFyeS5jbG9uZSgpLAogICAgICAgICAgICBzY3g6IFNoYXBlQ29udGV4dDo6bmV3KCksCiAgICAgICAgICAgIHN0YXRlczogRnhIYXNoTWFwOjpkZWZhdWx0KCksCiAgICAgICAgICAgIHdvcmRfY2FjaGU6IFdvcmRDYWNoZTo6bmV3KCksCiAgICAgICAgICAgIGZvbnRfZmVhdHVyZXM6IHZlYyFbXSwKICAgICAgICAgICAgc2VsZWN0b3I6IE5vbmUsCiAgICAgICAgfQogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHNlbCgmbXV0IHNlbGYsIHN0YXRlX2lkOiB1c2l6ZSkgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBzZWxmLnNlbGVjdG9yID0gU29tZShzdGF0ZV9pZCk7CgogICAgICAgIHNlbGYKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBmb250X2xpYnJhcnkoJnNlbGYpIC0+ICZGb250TGlicmFyeSB7CiAgICAgICAgJnNlbGYuZm9udHMKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBzZXRfZm9udF9saWJyYXJ5KCZtdXQgc2VsZiwgZm9udF9saWJyYXJ5OiAmRm9udExpYnJhcnkpIHsKICAgICAgICBzZWxmLmZvbnRzID0gZm9udF9saWJyYXJ5LmNsb25lKCk7CiAgICAgICAgc2VsZi53b3JkX2NhY2hlID0gV29yZENhY2hlOjpuZXcoKTsKICAgICAgICBmb3IgbGluZSBpbiBzZWxmLnN0YXRlcy52YWx1ZXNfbXV0KCkgewogICAgICAgICAgICBsaW5lLm1ldHJpY3NfY2FjaGUgPSBNZXRyaWNzQ2FjaGU6OmRlZmF1bHQoKTsKICAgICAgICB9CiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gZ2V0X3N0YXRlKCZzZWxmLCBzdGF0ZV9pZDogJnVzaXplKSAtPiBPcHRpb248JkJ1aWxkZXJTdGF0ZT4gewogICAgICAgIHNlbGYuc3RhdGVzLmdldChzdGF0ZV9pZCkKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBnZXRfc3RhdGVfbXV0KCZtdXQgc2VsZiwgc3RhdGVfaWQ6ICZ1c2l6ZSkgLT4gT3B0aW9uPCZtdXQgQnVpbGRlclN0YXRlPiB7CiAgICAgICAgc2VsZi5zdGF0ZXMuZ2V0X211dChzdGF0ZV9pZCkKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBzZXRfZm9udF9mZWF0dXJlcygKICAgICAgICAmbXV0IHNlbGYsCiAgICAgICAgZm9udF9mZWF0dXJlczogVmVjPGNyYXRlOjpmb250X2ludHJvc3BlY3Rvcjo6U2V0dGluZzx1MTY+PiwKICAgICkgewogICAgICAgIHNlbGYuZm9udF9mZWF0dXJlcyA9IGZvbnRfZmVhdHVyZXM7CiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gY3JlYXRlX3N0YXRlKCZtdXQgc2VsZiwgcmljaF90ZXh0X2xheW91dDogJlJpY2hUZXh0TGF5b3V0KSAtPiB1c2l6ZSB7CiAgICAgICAgbGV0IGlkID0gc2VsZi5zdGF0ZXMubGVuKCk7CiAgICAgICAgc2VsZi5zdGF0ZXMKICAgICAgICAgICAgLmluc2VydChpZCwgQnVpbGRlclN0YXRlOjpmcm9tX2xheW91dChyaWNoX3RleHRfbGF5b3V0KSk7CiAgICAgICAgaWQKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiB1cGRhdGVfZGltZW5zaW9ucygKICAgICAgICAmbXV0IHNlbGYsCiAgICAgICAgc3RhdGVfaWQ6ICZ1c2l6ZSwKICAgICAgICBhZHZhbmNlX2JydXNoOiAmbXV0IFJpY2hUZXh0QnJ1c2gsCiAgICApIHsKICAgICAgICBsZXQgbXV0IGNvbnRlbnQgPSBDb250ZW50OjpuZXcoJnNlbGYuZm9udHMpOwogICAgICAgIGlmIGxldCBTb21lKHJ0ZSkgPSBzZWxmLnN0YXRlcy5nZXRfbXV0KHN0YXRlX2lkKSB7CiAgICAgICAgICAgIGxldCBpZCA9IGNvbnRlbnQuY3JlYXRlX3N0YXRlKCZydGUubGF5b3V0KTsKICAgICAgICAgICAgY29udGVudAogICAgICAgICAgICAgICAgLnNlbChpZCkKICAgICAgICAgICAgICAgIC5uZXdfbGluZSgpCiAgICAgICAgICAgICAgICAuYWRkX3RleHQoIiAiLCBGcmFnbWVudFN0eWxlOjpkZWZhdWx0KCkpCiAgICAgICAgICAgICAgICAuYnVpbGQoKTsKICAgICAgICAgICAgbGV0IHJlbmRlcl9kYXRhID0gY29udGVudC5nZXRfc3RhdGUoJmlkKS51bndyYXAoKS5saW5lc1swXS5jbG9uZSgpOwoKICAgICAgICAgICAgaWYgbGV0IFNvbWUoZGltZW5zaW9uKSA9IGFkdmFuY2VfYnJ1c2guZGltZW5zaW9ucygmc2VsZi5mb250cywgJnJlbmRlcl9kYXRhKSB7CiAgICAgICAgICAgICAgICBydGUubGF5b3V0LmRpbWVuc2lvbnMuaGVpZ2h0ID0gZGltZW5zaW9uLmhlaWdodCAqIHJ0ZS5sYXlvdXQubGluZV9oZWlnaHQ7CiAgICAgICAgICAgICAgICBydGUubGF5b3V0LmRpbWVuc2lvbnMud2lkdGggPSBkaW1lbnNpb24ud2lkdGg7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gY2xlYXJfc3RhdGUoJm11dCBzZWxmLCBpZDogJnVzaXplKSB7CiAgICAgICAgaWYgbGV0IFNvbWUoc3RhdGUpID0gc2VsZi5zdGF0ZXMuZ2V0X211dChpZCkgewogICAgICAgICAgICBzdGF0ZS5jbGVhcigpOwogICAgICAgICAgICBzdGF0ZS5iZWdpbigpOwogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBuZXdfbGluZV93aXRoX2lkKCZtdXQgc2VsZiwgaWQ6ICZ1c2l6ZSkgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBpZiBsZXQgU29tZShjb250ZW50KSA9IHNlbGYuc3RhdGVzLmdldF9tdXQoaWQpIHsKICAgICAgICAgICAgY29udGVudC5uZXdfbGluZSgpOwogICAgICAgIH0KCiAgICAgICAgc2VsZgogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIG5ld19saW5lKCZtdXQgc2VsZikgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBpZiBsZXQgU29tZShzZWxlY3RvcikgPSBzZWxmLnNlbGVjdG9yIHsKICAgICAgICAgICAgcmV0dXJuIHNlbGYubmV3X2xpbmVfd2l0aF9pZCgmc2VsZWN0b3IpOwogICAgICAgIH0KCiAgICAgICAgc2VsZgogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIGNsZWFyX2xpbmUoJm11dCBzZWxmLCBsaW5lX3RvX2NsZWFyOiB1c2l6ZSkgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBpZiBsZXQgU29tZShzZWxlY3RvcikgPSBzZWxmLnNlbGVjdG9yIHsKICAgICAgICAgICAgaWYgbGV0IFNvbWUoc3RhdGUpID0gc2VsZi5zdGF0ZXMuZ2V0X211dCgmc2VsZWN0b3IpIHsKICAgICAgICAgICAgICAgIHN0YXRlLmxpbmVzW2xpbmVfdG9fY2xlYXJdLmZyYWdtZW50cy5jbGVhcigpOwogICAgICAgICAgICAgICAgc3RhdGUubGluZXNbbGluZV90b19jbGVhcl0ucmVuZGVyX2RhdGEuY2xlYXIoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgc2VsZgogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIGNsZWFyX3dpdGhfaWQoJm11dCBzZWxmLCBpZDogJnVzaXplKSAtPiAmbXV0IENvbnRlbnQgewogICAgICAgIGlmIGxldCBTb21lKHN0YXRlKSA9IHNlbGYuc3RhdGVzLmdldF9tdXQoaWQpIHsKICAgICAgICAgICAgc3RhdGUuY2xlYXIoKTsKICAgICAgICAgICAgc3RhdGUuYmVnaW4oKTsKICAgICAgICB9CgogICAgICAgIHNlbGYKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBjbGVhcl9hbGwoJm11dCBzZWxmKSAtPiAmbXV0IENvbnRlbnQgewogICAgICAgIGZvciBzdGF0ZSBpbiAmbXV0IHNlbGYuc3RhdGVzLnZhbHVlc19tdXQoKSB7CiAgICAgICAgICAgIHN0YXRlLmNsZWFyKCk7CiAgICAgICAgICAgIHN0YXRlLmJlZ2luKCk7CiAgICAgICAgfQoKICAgICAgICBzZWxmCiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gY2xlYXIoJm11dCBzZWxmKSAtPiAmbXV0IENvbnRlbnQgewogICAgICAgIGlmIGxldCBTb21lKHNlbGVjdG9yKSA9IHNlbGYuc2VsZWN0b3IgewogICAgICAgICAgICByZXR1cm4gc2VsZi5jbGVhcl93aXRoX2lkKCZzZWxlY3Rvcik7CiAgICAgICAgfQoKICAgICAgICBzZWxmCiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gYWRkX3RleHQoJm11dCBzZWxmLCB0ZXh0OiAmc3RyLCBzdHlsZTogRnJhZ21lbnRTdHlsZSkgLT4gJm11dCBDb250ZW50IHsKICAgICAgICBpZiBsZXQgU29tZShzZWxlY3RvcikgPSBzZWxmLnNlbGVjdG9yIHsKICAgICAgICAgICAgcmV0dXJuIHNlbGYuYWRkX3RleHRfd2l0aF9pZCgmc2VsZWN0b3IsIHRleHQsIHN0eWxlKTsKICAgICAgICB9CgogICAgICAgIHNlbGYKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBhZGRfdGV4dF9vbl9saW5lKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBsaW5lOiB1c2l6ZSwKICAgICAgICB0ZXh0OiAmc3RyLAogICAgICAgIHN0eWxlOiBGcmFnbWVudFN0eWxlLAogICAgKSAtPiAmbXV0IENvbnRlbnQgewogICAgICAgIGlmIGxldCBTb21lKHNlbGVjdG9yKSA9IHNlbGYuc2VsZWN0b3IgewogICAgICAgICAgICBpZiBsZXQgU29tZShzdGF0ZSkgPSBzZWxmLnN0YXRlcy5nZXRfbXV0KCZzZWxlY3RvcikgewogICAgICAgICAgICAgICAgbGV0IGxpbmUgPSAmbXV0IHN0YXRlLmxpbmVzW2xpbmVdOwoKICAgICAgICAgICAgICAgIGxpbmUuZnJhZ21lbnRzLnB1c2goRnJhZ21lbnREYXRhIHsKICAgICAgICAgICAgICAgICAgICBjb250ZW50OiB0ZXh0LnRvX3N0cmluZygpLAogICAgICAgICAgICAgICAgICAgIHN0eWxlLAogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIHNlbGYKICAgIH0KCiAgICAvLy8gQWRkcyBhIHRleHQgZnJhZ21lbnQgdG8gdGhlIHBhcmFncmFwaC4KICAgIHB1YiBmbiBhZGRfdGV4dF93aXRoX2lkKAogICAgICAgICZtdXQgc2VsZiwKICAgICAgICBpZDogJnVzaXplLAogICAgICAgIHRleHQ6ICZzdHIsCiAgICAgICAgc3R5bGU6IEZyYWdtZW50U3R5bGUsCiAgICApIC0+ICZtdXQgQ29udGVudCB7CiAgICAgICAgaWYgbGV0IFNvbWUoc3RhdGUpID0gc2VsZi5zdGF0ZXMuZ2V0X211dChpZCkgewogICAgICAgICAgICBsZXQgY3VycmVudF9saW5lID0gc3RhdGUuY3VycmVudF9saW5lKCk7CiAgICAgICAgICAgIGlmIGxldCBTb21lKGxpbmUpID0gJm11dCBzdGF0ZS5saW5lcy5nZXRfbXV0KGN1cnJlbnRfbGluZSkgewogICAgICAgICAgICAgICAgbGluZS5mcmFnbWVudHMucHVzaChGcmFnbWVudERhdGEgewogICAgICAgICAgICAgICAgICAgIGNvbnRlbnQ6IHRleHQudG9fc3RyaW5nKCksCiAgICAgICAgICAgICAgICAgICAgc3R5bGUsCiAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgc2VsZgogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIGJ1aWxkKCZtdXQgc2VsZikgewogICAgICAgIGlmIGxldCBTb21lKHNlbGVjdG9yKSA9IHNlbGYuc2VsZWN0b3IgewogICAgICAgICAgICBpZiBsZXQgU29tZShzdGF0ZSkgPSBzZWxmLnN0YXRlcy5nZXRfbXV0KCZzZWxlY3RvcikgewogICAgICAgICAgICAgICAgbGV0IHNjcmlwdCA9IFNjcmlwdDo6TGF0aW47CiAgICAgICAgICAgICAgICBmb3IgbGluZV9udW1iZXIgaW4gMC4uc3RhdGUubGluZXMubGVuKCkgewogICAgICAgICAgICAgICAgICAgIGxldCBsaW5lID0gJm11dCBzdGF0ZS5saW5lc1tsaW5lX251bWJlcl07CiAgICAgICAgICAgICAgICAgICAgZm9yIGl0ZW0gaW4gJmxpbmUuZnJhZ21lbnRzIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHZhcnMgPSBzdGF0ZS52YXJzLmdldChpdGVtLnN0eWxlLmZvbnRfdmFycyk7CiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBzaGFwZXJfa2V5ID0gJml0ZW0uY29udGVudDsKCiAgICAgICAgICAgICAgICAgICAgICAgIC8vIHByaW50bG4hKCJ7Oj99IC0+IHs6P30iLCBpdGVtLnN0eWxlLmZvbnRfaWQsIHNoYXBlcl9rZXkpOwoKICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGV0IFNvbWUoc2hhcGVyKSA9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLndvcmRfY2FjaGUuZ2V0KCZpdGVtLnN0eWxlLmZvbnRfaWQsIHNoYXBlcl9rZXkpCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIGxldCBTb21lKG1ldHJpY3MpID0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5tZXRyaWNzX2NhY2hlLmlubmVyLmdldCgmaXRlbS5zdHlsZS5mb250X2lkKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIGxpbmUucmVuZGVyX2RhdGEucHVzaF9ydW5fd2l0aG91dF9zaGFwZXIoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uc3R5bGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnNjYWxlZF9mb250X3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmVfbnVtYmVyIGFzIHUzMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hhcGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYud29yZF9jYWNoZS5mb250X2lkID0gaXRlbS5zdHlsZS5mb250X2lkOwogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLndvcmRfY2FjaGUuY29udGVudCA9IGl0ZW0uY29udGVudC5jbG9uZSgpOwogICAgICAgICAgICAgICAgICAgICAgICBsZXQgZm9udF9saWJyYXJ5ID0geyAmbXV0IHNlbGYuZm9udHMuaW5uZXIubG9jaygpIH07CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIGxldCBTb21lKGRhdGEpID0gZm9udF9saWJyYXJ5LmdldF9kYXRhKCZpdGVtLnN0eWxlLmZvbnRfaWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBtdXQgc2hhcGVyID0gc2VsZgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zY3gKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYnVpbGRlcihkYXRhKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zY3JpcHQoc2NyaXB0KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zaXplKHN0YXRlLnNjYWxlZF9mb250X3NpemUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZlYXR1cmVzKHNlbGYuZm9udF9mZWF0dXJlcy5pdGVyKCkuY29waWVkKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnZhcmlhdGlvbnModmFycy5pdGVyKCkuY29waWVkKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmJ1aWxkKCk7CgogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hhcGVyLmFkZF9zdHIoJnNlbGYud29yZF9jYWNoZS5jb250ZW50KTsKCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tZXRyaWNzX2NhY2hlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmlubmVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmVudHJ5KGl0ZW0uc3R5bGUuZm9udF9pZCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAub3JfaW5zZXJ0X3dpdGgofHwgc2hhcGVyLm1ldHJpY3MoKSk7CgogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZS5yZW5kZXJfZGF0YS5wdXNoX3J1bigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLnN0eWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnNjYWxlZF9mb250X3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV9udW1iZXIgYXMgdTMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAmbXV0IHNlbGYud29yZF9jYWNoZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gYnVpbGRfbGluZSgmbXV0IHNlbGYsIGxpbmVfbnVtYmVyOiB1c2l6ZSkgewogICAgICAgIGlmIGxldCBTb21lKHNlbGVjdG9yKSA9IHNlbGYuc2VsZWN0b3IgewogICAgICAgICAgICBpZiBsZXQgU29tZShzdGF0ZSkgPSBzZWxmLnN0YXRlcy5nZXRfbXV0KCZzZWxlY3RvcikgewogICAgICAgICAgICAgICAgbGV0IHNjcmlwdCA9IFNjcmlwdDo6TGF0aW47CiAgICAgICAgICAgICAgICBsZXQgbGluZSA9ICZtdXQgc3RhdGUubGluZXNbbGluZV9udW1iZXJdOwogICAgICAgICAgICAgICAgZm9yIGl0ZW0gaW4gJmxpbmUuZnJhZ21lbnRzIHsKICAgICAgICAgICAgICAgICAgICBsZXQgdmFycyA9IHN0YXRlLnZhcnMuZ2V0KGl0ZW0uc3R5bGUuZm9udF92YXJzKTsKICAgICAgICAgICAgICAgICAgICBsZXQgc2hhcGVyX2tleSA9ICZpdGVtLmNvbnRlbnQ7CgogICAgICAgICAgICAgICAgICAgIC8vIHByaW50bG4hKCJ7Oj99IC0+IHs6P30iLCBpdGVtLnN0eWxlLmZvbnRfaWQsIHNoYXBlcl9rZXkpOwoKICAgICAgICAgICAgICAgICAgICBpZiBsZXQgU29tZShzaGFwZXIpID0KICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi53b3JkX2NhY2hlLmdldCgmaXRlbS5zdHlsZS5mb250X2lkLCBzaGFwZXJfa2V5KQogICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGV0IFNvbWUobWV0cmljcykgPQogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGUubWV0cmljc19jYWNoZS5pbm5lci5nZXQoJml0ZW0uc3R5bGUuZm9udF9pZCkKICAgICAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGluZS5yZW5kZXJfZGF0YS5wdXNoX3J1bl93aXRob3V0X3NoYXBlcigKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtLnN0eWxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlLnNjYWxlZF9mb250X3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV9udW1iZXIgYXMgdTMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXBlciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRyaWNzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgICAgIHNlbGYud29yZF9jYWNoZS5mb250X2lkID0gaXRlbS5zdHlsZS5mb250X2lkOwogICAgICAgICAgICAgICAgICAgIHNlbGYud29yZF9jYWNoZS5jb250ZW50ID0gaXRlbS5jb250ZW50LmNsb25lKCk7CiAgICAgICAgICAgICAgICAgICAgbGV0IGZvbnRfbGlicmFyeSA9IHsgJm11dCBzZWxmLmZvbnRzLmlubmVyLmxvY2soKSB9OwogICAgICAgICAgICAgICAgICAgIGlmIGxldCBTb21lKGRhdGEpID0gZm9udF9saWJyYXJ5LmdldF9kYXRhKCZpdGVtLnN0eWxlLmZvbnRfaWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG11dCBzaGFwZXIgPSBzZWxmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuc2N4CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYnVpbGRlcihkYXRhKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLnNjcmlwdChzY3JpcHQpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuc2l6ZShzdGF0ZS5zY2FsZWRfZm9udF9zaXplKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLmZlYXR1cmVzKHNlbGYuZm9udF9mZWF0dXJlcy5pdGVyKCkuY29waWVkKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAudmFyaWF0aW9ucyh2YXJzLml0ZXIoKS5jb3BpZWQoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5idWlsZCgpOwoKICAgICAgICAgICAgICAgICAgICAgICAgc2hhcGVyLmFkZF9zdHIoJnNlbGYud29yZF9jYWNoZS5jb250ZW50KTsKCiAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAubWV0cmljc19jYWNoZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLmlubmVyCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZW50cnkoaXRlbS5zdHlsZS5mb250X2lkKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgLm9yX2luc2VydF93aXRoKHx8IHNoYXBlci5tZXRyaWNzKCkpOwoKICAgICAgICAgICAgICAgICAgICAgICAgbGluZS5yZW5kZXJfZGF0YS5wdXNoX3J1bigKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0uc3R5bGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGF0ZS5zY2FsZWRfZm9udF9zaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZV9udW1iZXIgYXMgdTMyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hhcGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgJm11dCBzZWxmLndvcmRfY2FjaGUsCiAgICAgICAgICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9CgpwdWIgc3RydWN0IFdvcmRDYWNoZSB7CiAgICBwdWIgaW5uZXI6IEZ4SGFzaE1hcDx1c2l6ZSwgTHJ1Q2FjaGU8U3RyaW5nLCBWZWM8T3duZWRHbHlwaENsdXN0ZXI+Pj4sCiAgICBzdGFzaDogVmVjPE93bmVkR2x5cGhDbHVzdGVyPiwKICAgIGZvbnRfaWQ6IHVzaXplLAogICAgY29udGVudDogU3RyaW5nLAp9CgppbXBsIFdvcmRDYWNoZSB7CiAgICBwdWIgZm4gbmV3KCkgLT4gU2VsZiB7CiAgICAgICAgV29yZENhY2hlIHsKICAgICAgICAgICAgaW5uZXI6IEZ4SGFzaE1hcDo6ZGVmYXVsdCgpLAogICAgICAgICAgICBzdGFzaDogdmVjIVtdLAogICAgICAgICAgICBmb250X2lkOiAwLAogICAgICAgICAgICBjb250ZW50OiBTdHJpbmc6Om5ldygpLAogICAgICAgIH0KICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBnZXQoCiAgICAgICAgJm11dCBzZWxmLAogICAgICAgIGZvbnRfaWQ6ICZ1c2l6ZSwKICAgICAgICBjb250ZW50OiAmU3RyaW5nLAogICAgKSAtPiBPcHRpb248JlZlYzxPd25lZEdseXBoQ2x1c3Rlcj4+IHsKICAgICAgICBpZiBsZXQgU29tZShjYWNoZSkgPSBzZWxmLmlubmVyLmdldF9tdXQoZm9udF9pZCkgewogICAgICAgICAgICByZXR1cm4gY2FjaGUuZ2V0KGNvbnRlbnQpOwogICAgICAgIH0KICAgICAgICBOb25lCiAgICB9CgogICAgI1tpbmxpbmVdCiAgICBwdWIgZm4gYWRkX2dseXBoX2NsdXN0ZXIoJm11dCBzZWxmLCBnbHlwaF9jbHVzdGVyOiAmR2x5cGhDbHVzdGVyKSB7CiAgICAgICAgc2VsZi5zdGFzaC5wdXNoKGdseXBoX2NsdXN0ZXIuaW50bygpKTsKICAgIH0KCiAgICAjW2lubGluZV0KICAgIHB1YiBmbiBmaW5pc2goJm11dCBzZWxmKSB7CiAgICAgICAgaWYgIXNlbGYuY29udGVudC5pc19lbXB0eSgpICYmICFzZWxmLnN0YXNoLmlzX2VtcHR5KCkgewogICAgICAgICAgICBpZiBsZXQgU29tZShjYWNoZSkgPSBzZWxmLmlubmVyLmdldF9tdXQoJnNlbGYuZm9udF9pZCkgewogICAgICAgICAgICAgICAgLy8gcHJpbnRsbiEoIns6P30gezo/fSIsIHNlbGYuY29udGVudCwgY2FjaGUubGVuKCkpOwogICAgICAgICAgICAgICAgY2FjaGUucHV0KAogICAgICAgICAgICAgICAgICAgIHN0ZDo6bWVtOjp0YWtlKCZtdXQgc2VsZi5jb250ZW50KSwKICAgICAgICAgICAgICAgICAgICBzdGQ6Om1lbTo6dGFrZSgmbXV0IHNlbGYuc3Rhc2gpLAogICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIC8vIElmIGZvbnQgaWQgaXMgbWFpbgogICAgICAgICAgICAgICAgbGV0IHNpemUgPSBpZiBzZWxmLmZvbnRfaWQgPT0gMCB7IDUxMiB9IGVsc2UgeyAxMjggfTsKICAgICAgICAgICAgICAgIGxldCBtdXQgY2FjaGUgPSBMcnVDYWNoZTo6bmV3KE5vblplcm9Vc2l6ZTo6bmV3KHNpemUpLnVud3JhcCgpKTsKICAgICAgICAgICAgICAgIGNhY2hlLnB1dCgKICAgICAgICAgICAgICAgICAgICBzdGQ6Om1lbTo6dGFrZSgmbXV0IHNlbGYuY29udGVudCksCiAgICAgICAgICAgICAgICAgICAgc3RkOjptZW06OnRha2UoJm11dCBzZWxmLnN0YXNoKSwKICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICBzZWxmLmlubmVyLmluc2VydChzZWxmLmZvbnRfaWQsIGNhY2hlKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgc2VsZi5mb250X2lkID0gMDsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgICBzZWxmLnN0YXNoLmNsZWFyKCk7CiAgICAgICAgc2VsZi5mb250X2lkID0gMDsKICAgICAgICBzZWxmLmNvbnRlbnQuY2xlYXIoKTsKICAgIH0KfQoKI1tkZXJpdmUoRGVmYXVsdCldCnN0cnVjdCBNZXRyaWNzQ2FjaGUgewogICAgcHViIGlubmVyOiBGeEhhc2hNYXA8dXNpemUsIE1ldHJpY3M+LAp9CgAAAAAAAAAABUwAAAAAAAAAAAAAAAAAAAAAAAAFTAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAIAAAARAwAAAAAAABwDAAAAAAAAAAAAAAAA8L/7FgAAAAAAAAYXAAAAAAAAAAAAAAAA8L8" - ] - ] - }, - { - "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/lib.rs", - "redo_stack": - [ - [ - 8, - 1, - "insert", - { - "characters": "content" - }, - "EAAAAFwAAAAAAAAAXAAAAAAAAAABAAAAdF4CAAAAAAAAXgIAAAAAAAABAAAAdFsAAAAAAAAAWwAAAAAAAAABAAAAblwCAAAAAAAAXAIAAAAAAAABAAAAbloAAAAAAAAAWgAAAAAAAAABAAAAZVoCAAAAAAAAWgIAAAAAAAABAAAAZVkAAAAAAAAAWQAAAAAAAAABAAAAdFgCAAAAAAAAWAIAAAAAAAABAAAAdFgAAAAAAAAAWAAAAAAAAAABAAAAblYCAAAAAAAAVgIAAAAAAAABAAAAblcAAAAAAAAAVwAAAAAAAAABAAAAb1QCAAAAAAAAVAIAAAAAAAABAAAAb1cAAAAAAAAAXQAAAAAAAAAAAAAAVgAAAAAAAABWAAAAAAAAAAEAAABjWQIAAAAAAABfAgAAAAAAAAAAAABYAgAAAAAAAFgCAAAAAAAAAQAAAGM", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAIAAABdAAAAAAAAAF0AAAAAAAAAAAAAAAAA8L9gAgAAAAAAAGACAAAAAAAAAAAAAAAA8L8" - ] - ], - "settings": - { - "buffer_size": 718, - "encoding": "UTF-8", - "line_ending": "Unix" - } - }, - { - "file": "/Users/rapha/Documents/a/rio/sugarloaf/Cargo.toml", - "settings": - { - "buffer_size": 6744, - "line_ending": "Unix" - }, - "undo_stack": - [ - [ - 10, - 1, - "paste", - null, - "AgAAAKcDAAAAAAAAuwMAAAAAAAAAAAAAuwMAAAAAAAC7AwAAAAAAAC8AAAB7IHZlcnNpb24gPSAiMS4xNy4wIiwgZmVhdHVyZXMgPSBbICJkZXJpdmUiIF0gfQ", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAACnAwAAAAAAANYDAAAAAAAA////////738" - ], - [ - 13, - 1, - "paste", - null, - "AgAAAMYDAAAAAAAA2gMAAAAAAAAAAAAA2gMAAAAAAADaAwAAAAAAAAgAAAAiMC4xLjQwIg", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADOAwAAAAAAAMYDAAAAAAAAAAAAAAAA8L8" - ], - [ - 25, - 1, - "paste", - null, - "AgAAAO0EAAAAAAAAAQUAAAAAAAAAAAAAAQUAAAAAAAABBQAAAAAAAAcAAAAiMC4yLjAi", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAADtBAAAAAAAAPQEAAAAAAAA////////738" - ], - [ - 35, - 1, - "insert", - { - "characters": "26" - }, - "AwAAAEgGAAAAAAAASQYAAAAAAAAAAAAASQYAAAAAAABJBgAAAAAAAAIAAAAyNUkGAAAAAAAASgYAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABIBgAAAAAAAEoGAAAAAAAAAAAAAAAA8L8" - ], - [ - 37, - 1, - "left_delete", - null, - "AQAAAEsGAAAAAAAASwYAAAAAAAABAAAAMA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABMBgAAAAAAAEwGAAAAAAAAAAAAAAAA8L8" - ], - [ - 38, - 1, - "insert", - { - "characters": "2" - }, - "AQAAAEsGAAAAAAAATAYAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAABLBgAAAAAAAEsGAAAAAAAAAAAAAAAA8L8" - ], - [ - 43, - 1, - "revert", - null, - "AwAAAAAAAAAAAAAAAAAAAAAAAABYGgAAW3BhY2thZ2VdCm5hbWUgPSAic3VnYXJsb2FmIgp2ZXJzaW9uLndvcmtzcGFjZSA9IHRydWUKZWRpdGlvbi53b3Jrc3BhY2UgPSB0cnVlCmxpY2Vuc2Uud29ya3NwYWNlID0gdHJ1ZQphdXRob3JzID0gWyJSYXBoYWVsIEFtb3JpbSA8cmFwaGE4NTBAZ21haWwuY29tPiJdCmluY2x1ZGUgPSBbCiAgIkNhcmdvLnRvbWwiLAogICJzcmMvKiovKi50dGYiLAogICJzcmMvKiovKi5vdGYiLAogICJzcmMvKiovKi53Z3NsIiwKICAic3JjLyoqLyoucnMiCl0KZGVzY3JpcHRpb24gPSAiU3VnYXJsb2FmIGlzIFJpbyByZW5kZXJpbmcgZW5naW5lLCBkZXNpZ25lZCB0byBiZSBtdWx0aXBsYXRmb3JtLiBJdCBpcyBiYXNlZCBvbiBXZWJHUFUsIFJ1c3QgbGlicmFyeSBmb3IgRGVza3RvcHMgYW5kIFdlYkFzc2VtYmx5IGZvciBXZWIgKEphdmFTY3JpcHQpLiBUaGlzIHByb2plY3QgaXMgY3JlYXRlZCBhbmQgbWFpbnRhaW5lZCBmb3IgUmlvIHRlcm1pbmFsIHB1cnBvc2VzIGJ1dCBmZWVsIGZyZWUgdG8gdXNlIGl0LiIKZG9jdW1lbnRhdGlvbiA9ICJodHRwczovL2RvY3MucnMvY3JhdGUvc3VnYXJsb2FmL2xhdGVzdCIKcmVwb3NpdG9yeSA9ICJodHRwczovL2dpdGh1Yi5jb20vcmFwaGFtb3JpbS9zdWdhcmxvYWYiCgpbbGliXQpjcmF0ZS10eXBlID0gWyJjZHlsaWIiLCAicmxpYiJdCgpbcGFja2FnZS5tZXRhZGF0YS5kb2NzLnJzXQphbGwtZmVhdHVyZXMgPSB0cnVlCnJ1c3Rkb2MtYXJncyA9IFsiLS1jZmciLCAiZG9jc3JzIl0KdGFyZ2V0cyA9IFsKICAgICJ4ODZfNjQtdW5rbm93bi1saW51eC1nbnUiLAogICAgIng4Nl82NC1hcHBsZS1kYXJ3aW4iLAogICAgIng4Nl82NC1wYy13aW5kb3dzLW1zdmMiLAogICAgIndhc20zMi11bmtub3duLXVua25vd24iLApdCgpbZGVwZW5kZW5jaWVzXQp3Z3B1ID0geyB3b3Jrc3BhY2UgPSB0cnVlIH0KYnl0ZW11Y2sgPSB7IHdvcmtzcGFjZSA9IHRydWUgfQp0cmFjaW5nID0geyB3b3Jrc3BhY2UgPSB0cnVlIH0Kc2VyZGUgPSB7IHZlcnNpb24gPSAiMS4wLjIwOCIsIGZlYXR1cmVzID0gWyJkZXJpdmUiXSB9CnR3b3gtaGFzaCA9IHsgdmVyc2lvbiA9ICIxLjYuMyIsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CmltYWdlX3JzID0geyBwYWNrYWdlID0gImltYWdlIiwgdmVyc2lvbiA9ICIwLjI1LjUiLCBkZWZhdWx0LWZlYXR1cmVzID0gZmFsc2UsIGZlYXR1cmVzID0gWyJnaWYiLCAianBlZyIsICJpY28iLCAicG5nIiwgInBubSIsICJ3ZWJwIiwgImJtcCJdIH0KdW5pY29kZS13aWR0aCA9IHsgd29ya3NwYWNlID0gdHJ1ZSB9Cmd1aWxsb3RpZXJlID0gIjAuNi4yIgpvcmRlcmVkLWZsb2F0ID0gIjQuNS4wIgpydXN0Yy1oYXNoID0gIjIuMC4wIgpyYXctd2luZG93LWhhbmRsZSA9IHsgdmVyc2lvbiA9ICIwLjYuMiIsIGZlYXR1cmVzID0gWyJzdGQiXSB9CnBhcmtpbmdfbG90ID0geyB2ZXJzaW9uID0gIjAuMTIuMyIsIGZlYXR1cmVzID0gWyJuaWdodGx5IiwgImhhcmR3YXJlLWxvY2stZWxpc2lvbiJdIH0KYWJfZ2x5cGggPSAiMC4yLjI5IgpsaW5rZWQtaGFzaC1tYXAgPSAiMC41LjYiCnhpLXVuaWNvZGUgPSAiMC4zLjAiCmFwcHJveCA9ICIwLjUuMSIKbHJ1ID0gIjAuMTIuNSIKc2tyaWZhID0gIjAuMjYuMiIKaGFsZmJyb3duID0gIjAuMi41IgpudW0tdHJhaXRzID0gIjAuMi4xOSIKeWF6aSA9IHsgdmVyc2lvbiA9ICIwLjIuMCIsIG9wdGlvbmFsID0gdHJ1ZSB9Cnplbm8gPSB7IHZlcnNpb24gPSAiMC4yLjMiLCBvcHRpb25hbCA9IHRydWUsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CmZ1dHVyZXMgPSAiMC4zLjMxIgoKbGlicmFzaGFkZXItY29tbW9uID0gIjAuNi4yIgpsaWJyYXNoYWRlci1wcmVzZXRzID0gIjAuNi4yIgpsaWJyYXNoYWRlci1wcmVwcm9jZXNzID0gIjAuNi4yIgpsaWJyYXNoYWRlci1wYWNrID0gIjAuNi4yIgpsaWJyYXNoYWRlci1yZWZsZWN0ID0geyB2ZXJzaW9uID0gIjAuNi4yIiwgZmVhdHVyZXMgPSBbInN0YWJsZSIsICJ3Z3NsIl0sIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CmxpYnJhc2hhZGVyLXJ1bnRpbWUgPSAiMC42LjIiCmxpYnJhc2hhZGVyLWNhY2hlID0gIjAuNi4yIgp0aGlzZXJyb3IgPSAiMi4wLjEiCmFycmF5LWNvbmNhdCA9ICIwLjUuMiIKClt0YXJnZXQuJ2NmZyhub3QodGFyZ2V0X2FyY2ggPSAid2FzbTMyIikpJy5kZXBlbmRlbmNpZXNdCmNyb3NzYmVhbS1jaGFubmVsID0gIjAuNS4xMyIKY3Jvc3NiZWFtLWRlcXVlID0gIjAuOC41IgpyYXlvbiA9ICIxLjEwLjAiCnR3b3gtaGFzaCA9IHsgdmVyc2lvbiA9ICIxLjYuMyIsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSwgZmVhdHVyZXMgPSBbInN0ZCJdIH0KbWVtbWFwMiA9ICIwLjkuMyIKc2xvdG1hcCA9IHsgdmVyc2lvbiA9ICIxLjAuNyIsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CnRpbnl2ZWMgPSB7IHZlcnNpb24gPSAiMS42LjAiLCBmZWF0dXJlcyA9IFsiYWxsb2MiXSB9CnR0Zi1wYXJzZXIgPSB7IHZlcnNpb24gPSAiMC4yNS4wIiB9CgpbdGFyZ2V0LidjZmcoYWxsKHVuaXgsIG5vdChhbnkodGFyZ2V0X29zID0gIm1hY29zIiwgdGFyZ2V0X29zID0gImFuZHJvaWQiKSkpKScuZGVwZW5kZW5jaWVzXQpmb250Y29uZmlnLXBhcnNlciA9IHsgdmVyc2lvbiA9ICIwLjUuNyIsIGRlZmF1bHQtZmVhdHVyZXMgPSBmYWxzZSB9CgpbZGV2LWRlcGVuZGVuY2llc10KcmlvLXdpbmRvdyA9ICIwLjIuMSIKcG5nID0gIjAuMTcuOCIKZGVmbGF0ZSA9ICIxLjAuMCIKY3JpdGVyaW9uID0gIjAuNS4xIgoKW2ZlYXR1cmVzXQpkZWZhdWx0ID0gWyJzY2FsZSIsICJyZW5kZXIiXQpzY2FsZSA9IFsieWF6aSIsICJ6ZW5vIl0KcmVuZGVyID0gWyJzY2FsZSIsICJ6ZW5vL2V2YWwiXQoKW3RhcmdldC4nY2ZnKHRhcmdldF9hcmNoID0gIndhc20zMiIpJy5kZXBlbmRlbmNpZXNdCmNvbnNvbGVfZXJyb3JfcGFuaWNfaG9vayA9ICIwLjEuNyIKY29uc29sZV9sb2cgPSAiMC4yLjIiCmpzLXN5cyA9ICIwLjMuNjEiCndhc20tYmluZGdlbiA9ICIwLjIuODciCndhc20tYmluZGdlbi1mdXR1cmVzID0gIjAuNC4zNCIKd2FzbS1iaW5kZ2VuLXRlc3QgPSAiMC4zLjQyIgp3ZWItc3lzID0geyB2ZXJzaW9uID0gIjAuMy42MSIsIGZlYXR1cmVzID0gWwogICAgIkxvY2F0aW9uIiwKICAgICJEb2N1bWVudCIsCiAgICAiTmF2aWdhdG9yIiwKICAgICJOb2RlIiwKICAgICJOb2RlTGlzdCIsCiAgICAiR3B1IiwKICAgICJHcHVBZGFwdGVyIiwKICAgICJHcHVBZGRyZXNzTW9kZSIsCiAgICAiR3B1QXV0b0xheW91dE1vZGUiLAogICAgIkdwdUJpbmRHcm91cCIsCiAgICAiR3B1QmluZEdyb3VwRGVzY3JpcHRvciIsCiAgICAiR3B1QmluZEdyb3VwRW50cnkiLAogICAgIkdwdUJpbmRHcm91cExheW91dCIsCiAgICAiR3B1QmluZEdyb3VwTGF5b3V0RGVzY3JpcHRvciIsCiAgICAiR3B1QmluZEdyb3VwTGF5b3V0RW50cnkiLAogICAgIkdwdUJsZW5kQ29tcG9uZW50IiwKICAgICJHcHVCbGVuZEZhY3RvciIsCiAgICAiR3B1QmxlbmRPcGVyYXRpb24iLAogICAgIkdwdUJsZW5kU3RhdGUiLAogICAgIkdwdUJ1ZmZlciIsCiAgICAiR3B1QnVmZmVyQmluZGluZyIsCiAgICAiR3B1QnVmZmVyQmluZGluZ0xheW91dCIsCiAgICAiR3B1QnVmZmVyQmluZGluZ1R5cGUiLAogICAgIkdwdUJ1ZmZlckRlc2NyaXB0b3IiLAogICAgIkdwdUNhbnZhc0FscGhhTW9kZSIsCiAgICAiR3B1Q2FudmFzQ29udGV4dCIsCiAgICAiR3B1Q2FudmFzQ29uZmlndXJhdGlvbiIsCiAgICAiR3B1Q29sb3JEaWN0IiwKICAgICJHcHVDb2xvclRhcmdldFN0YXRlIiwKICAgICJHcHVDb21tYW5kQnVmZmVyIiwKICAgICJHcHVDb21tYW5kQnVmZmVyRGVzY3JpcHRvciIsCiAgICAiR3B1Q29tbWFuZEVuY29kZXIiLAogICAgIkdwdUNvbW1hbmRFbmNvZGVyRGVzY3JpcHRvciIsCiAgICAiR3B1Q29tcGFyZUZ1bmN0aW9uIiwKICAgICJHcHVDb21waWxhdGlvbkluZm8iLAogICAgIkdwdUNvbXBpbGF0aW9uTWVzc2FnZSIsCiAgICAiR3B1Q29tcGlsYXRpb25NZXNzYWdlVHlwZSIsCiAgICAiR3B1Q29tcHV0ZVBhc3NEZXNjcmlwdG9yIiwKICAgICJHcHVDb21wdXRlUGFzc0VuY29kZXIiLAogICAgIkdwdUNvbXB1dGVQaXBlbGluZSIsCiAgICAiR3B1Q29tcHV0ZVBpcGVsaW5lRGVzY3JpcHRvciIsCiAgICAiR3B1Q3VsbE1vZGUiLAogICAgIkdwdURlcHRoU3RlbmNpbFN0YXRlIiwKICAgICJHcHVEZXZpY2UiLAogICAgIkdwdURldmljZURlc2NyaXB0b3IiLAogICAgIkdwdURldmljZUxvc3RJbmZvIiwKICAgICJHcHVEZXZpY2VMb3N0UmVhc29uIiwKICAgICJHcHVFcnJvciIsCiAgICAiR3B1RXJyb3JGaWx0ZXIiLAogICAgIyAiR3B1RXh0ZW50MmREaWN0IiwgTm90IHlldCBpbXBsZW1lbnRlZCBpbiB3ZWJfc3lzCiAgICAiR3B1RXh0ZW50M2REaWN0IiwKICAgICJHcHVGZWF0dXJlTmFtZSIsCiAgICAiR3B1RmlsdGVyTW9kZSIsCiAgICAiR3B1RnJhZ21lbnRTdGF0ZSIsCiAgICAiR3B1RnJvbnRGYWNlIiwKICAgICJHcHVJbWFnZUNvcHlCdWZmZXIiLAogICAgIkdwdUltYWdlQ29weUV4dGVybmFsSW1hZ2UiLAogICAgIkdwdUltYWdlQ29weVRleHR1cmUiLAogICAgIkdwdUltYWdlQ29weVRleHR1cmVUYWdnZWQiLAogICAgIkdwdUltYWdlRGF0YUxheW91dCIsCiAgICAiR3B1SW5kZXhGb3JtYXQiLAogICAgIkdwdUxvYWRPcCIsCiAgICAiZ3B1X21hcF9tb2RlIiwKICAgICJHcHVNaXBtYXBGaWx0ZXJNb2RlIiwKICAgICJHcHVNdWx0aXNhbXBsZVN0YXRlIiwKICAgICJHcHVPYmplY3REZXNjcmlwdG9yQmFzZSIsCiAgICAiR3B1T3JpZ2luMmREaWN0IiwKICAgICJHcHVPcmlnaW4zZERpY3QiLAogICAgIkdwdU91dE9mTWVtb3J5RXJyb3IiLAogICAgIkdwdVBpcGVsaW5lRGVzY3JpcHRvckJhc2UiLAogICAgIkdwdVBpcGVsaW5lTGF5b3V0IiwKICAgICJHcHVQaXBlbGluZUxheW91dERlc2NyaXB0b3IiLAogICAgIkdwdVBvd2VyUHJlZmVyZW5jZSIsCiAgICAiR3B1UHJpbWl0aXZlU3RhdGUiLAogICAgIkdwdVByaW1pdGl2ZVRvcG9sb2d5IiwKICAgICJHcHVQcm9ncmFtbWFibGVTdGFnZSIsCiAgICAiR3B1UXVlcnlTZXQiLAogICAgIkdwdVF1ZXJ5U2V0RGVzY3JpcHRvciIsCiAgICAiR3B1UXVlcnlUeXBlIiwKICAgICJHcHVRdWV1ZSIsCiAgICAiR3B1UmVuZGVyQnVuZGxlIiwKICAgICJHcHVSZW5kZXJCdW5kbGVEZXNjcmlwdG9yIiwKICAgICJHcHVSZW5kZXJCdW5kbGVFbmNvZGVyIiwKICAgICJHcHVSZW5kZXJCdW5kbGVFbmNvZGVyRGVzY3JpcHRvciIsCiAgICAiR3B1UmVuZGVyUGFzc0NvbG9yQXR0YWNobWVudCIsCiAgICAiR3B1UmVuZGVyUGFzc0RlcHRoU3RlbmNpbEF0dGFjaG1lbnQiLAogICAgIkdwdVJlbmRlclBhc3NEZXNjcmlwdG9yIiwKICAgICJHcHVSZW5kZXJQYXNzRW5jb2RlciIsCiAgICAiR3B1UmVuZGVyUGlwZWxpbmUiLAogICAgIkdwdVJlbmRlclBpcGVsaW5lRGVzY3JpcHRvciIsCiAgICAiR3B1UmVxdWVzdEFkYXB0ZXJPcHRpb25zIiwKICAgICJHcHVTYW1wbGVyIiwKICAgICJHcHVTYW1wbGVyQmluZGluZ0xheW91dCIsCiAgICAiR3B1U2FtcGxlckJpbmRpbmdUeXBlIiwKICAgICJHcHVTYW1wbGVyRGVzY3JpcHRvciIsCiAgICAiR3B1U2hhZGVyTW9kdWxlIiwKICAgICJHcHVTaGFkZXJNb2R1bGVEZXNjcmlwdG9yIiwKICAgICJHcHVTdGVuY2lsRmFjZVN0YXRlIiwKICAgICJHcHVTdGVuY2lsT3BlcmF0aW9uIiwKICAgICJHcHVTdG9yYWdlVGV4dHVyZUFjY2VzcyIsCiAgICAiR3B1U3RvcmFnZVRleHR1cmVCaW5kaW5nTGF5b3V0IiwKICAgICJHcHVTdG9yZU9wIiwKICAgICJHcHVTdXBwb3J0ZWRGZWF0dXJlcyIsCiAgICAiR3B1U3VwcG9ydGVkTGltaXRzIiwKICAgICJHcHVUZXh0dXJlIiwKICAgICJHcHVUZXh0dXJlQXNwZWN0IiwKICAgICJHcHVUZXh0dXJlQmluZGluZ0xheW91dCIsCiAgICAiR3B1VGV4dHVyZURlc2NyaXB0b3IiLAogICAgIkdwdVRleHR1cmVEaW1lbnNpb24iLAogICAgIkdwdVRleHR1cmVGb3JtYXQiLAogICAgIkdwdVRleHR1cmVTYW1wbGVUeXBlIiwKICAgICJHcHVUZXh0dXJlVmlldyIsCiAgICAiR3B1VGV4dHVyZVZpZXdEZXNjcmlwdG9yIiwKICAgICJHcHVUZXh0dXJlVmlld0RpbWVuc2lvbiIsCiAgICAiR3B1VW5jYXB0dXJlZEVycm9yRXZlbnQiLAogICAgIkdwdVVuY2FwdHVyZWRFcnJvckV2ZW50SW5pdCIsCiAgICAiR3B1VmFsaWRhdGlvbkVycm9yIiwKICAgICJHcHVWZXJ0ZXhBdHRyaWJ1dGUiLAogICAgIkdwdVZlcnRleEJ1ZmZlckxheW91dCIsCiAgICAiR3B1VmVydGV4Rm9ybWF0IiwKICAgICJHcHVWZXJ0ZXhTdGF0ZSIsCiAgICAiR3B1VmVydGV4U3RlcE1vZGUiLAogICAgIkh0bWxDYW52YXNFbGVtZW50IiwKICAgICJPZmZzY3JlZW5DYW52YXMiLAogICAgIkltYWdlQml0bWFwIiwKICAgICJJbWFnZUJpdG1hcFJlbmRlcmluZ0NvbnRleHQiLAogICAgIldpbmRvdyIsCiAgICAiV29ya2VyR2xvYmFsU2NvcGUiLAogICAgIldvcmtlck5hdmlnYXRvciIKXSB9CgpbdGFyZ2V0LidjZmcodGFyZ2V0X2FyY2ggPSAid2FzbTMyIiknLmRldi1kZXBlbmRlbmNpZXNdCndlYi1zeXMgPSB7IHZlcnNpb24gPSAiMC4zLjYxIiwgZmVhdHVyZXMgPSBbCiAgICAiTG9jYXRpb24iLAogICAgIkJsb2IiLAogICAgIlJlcXVlc3RJbml0IiwKICAgICJSZXF1ZXN0TW9kZSIsCiAgICAiUmVxdWVzdCIsCiAgICAiUmVzcG9uc2UiLAogICAgIldlYkdsMlJlbmRlcmluZ0NvbnRleHQiLAogICAgIkNhbnZhc1JlbmRlcmluZ0NvbnRleHQyZCIKXX0KAAAAAAAAAABYGgAAAAAAAAAAAAAAAAAAAAAAAFgaAAAAAAAAAAAAAA", - "AgAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAEAAAACBQAAAAAAAA0FAAAAAAAAAAAAAAAA8L8" - ] - ] - }, - { - "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/bindings/mod.rs", - "settings": - { - "buffer_size": 64085, - "line_ending": "Unix" - }, - "undo_stack": - [ - [ - 200, - 1, - "revert", - null, - "AgAAAAAAAAAAAAAAAAAAAAAAAABV+gAALy8gQmluZGluZzxUPiwgTW91c2VBY3Rpb24sIEJpbmRpbmdNb2RlLCBBY3Rpb24sIGRlZmF1bHRfa2V5X2JpbmRpbmdzIGFuZCBpbmNsdWRpbmcgdGhlaXIgY29tbWVudHMKLy8gd2FzIG9yaWdpbmFsbHkgdGFrZW4gZnJvbSBodHRwczovL2dpdGh1Yi5jb20vYWxhY3JpdHR5L2FsYWNyaXR0eS9ibG9iL2UzNWU1YWQxNGZjZTg0NTZhZmRkODlmMmIzOTJiOTkyNGJiMjc0NzEvYWxhY3JpdHR5L3NyYy9jb25maWcvYmluZGluZ3MucnMKLy8gd2hpY2ggaXMgbGljZW5zZWQgdW5kZXIgQXBhY2hlIDIuMCBsaWNlbnNlLgoKcHViIG1vZCBraXR0eV9rZXlib2FyZDsKCnVzZSBjcmF0ZTo6Y3Jvc3N3b3Jkczo6dmlfbW9kZTo6VmlNb3Rpb247CnVzZSBjcmF0ZTo6Y3Jvc3N3b3Jkczo6TW9kZTsKdXNlIGJpdGZsYWdzOjpiaXRmbGFnczsKdXNlIHJpb19iYWNrZW5kOjpjb25maWc6OmJpbmRpbmdzOjpLZXlCaW5kaW5nIGFzIENvbmZpZ0tleUJpbmRpbmc7CnVzZSByaW9fYmFja2VuZDo6Y29uZmlnOjprZXlib2FyZDo6S2V5Ym9hcmQgYXMgQ29uZmlnS2V5Ym9hcmQ7CnVzZSByaW9fd2luZG93OjpldmVudDo6TW91c2VCdXR0b247CnVzZSByaW9fd2luZG93OjprZXlib2FyZDo6S2V5OjoqOwp1c2UgcmlvX3dpbmRvdzo6a2V5Ym9hcmQ6Ok5hbWVkS2V5OjoqOwp1c2UgcmlvX3dpbmRvdzo6a2V5Ym9hcmQ6OntLZXksIEtleUxvY2F0aW9uLCBNb2RpZmllcnNTdGF0ZSwgUGh5c2ljYWxLZXl9Owp1c2Ugc3RkOjpmbXQ6OkRlYnVnOwovLyB1c2UgcmlvX3dpbmRvdzo6cGxhdGZvcm06OnNjYW5jb2RlOjpQaHlzaWNhbEtleUV4dFNjYW5jb2RlOwoKI1tkZXJpdmUoRGVidWcsIENsb25lLCBQYXJ0aWFsRXEsIEVxKV0KcHViIGVudW0gRm9udFNpemVBY3Rpb24gewogICAgSW5jcmVhc2UsCiAgICBEZWNyZWFzZSwKICAgIFJlc2V0LAp9CgovLy8gTW91c2UgYmluZGluZyBzcGVjaWZpYyBhY3Rpb25zLgojW2Rlcml2ZShEZWJ1ZywgQ29weSwgQ2xvbmUsIFBhcnRpYWxFcSwgRXEpXQpwdWIgZW51bSBNb3VzZUFjdGlvbiB7CiAgICAvLy8gRXhwYW5kIHRoZSBzZWxlY3Rpb24gdG8gdGhlIGN1cnJlbnQgbW91c2UgY3Vyc29yIHBvc2l0aW9uLgogICAgRXhwYW5kU2VsZWN0aW9uLAp9CgppbXBsIEZyb208TW91c2VBY3Rpb24+IGZvciBBY3Rpb24gewogICAgZm4gZnJvbShhY3Rpb246IE1vdXNlQWN0aW9uKSAtPiBTZWxmIHsKICAgICAgICBTZWxmOjpNb3VzZShhY3Rpb24pCiAgICB9Cn0KCi8vLyBTZWFyY2ggbW9kZSBzcGVjaWZpYyBhY3Rpb25zLgojW2FsbG93KGNsaXBweTo6ZW51bV92YXJpYW50X25hbWVzKV0KI1tkZXJpdmUoRGVidWcsIENvcHksIENsb25lLCBQYXJ0aWFsRXEsIEVxKV0KcHViIGVudW0gU2VhcmNoQWN0aW9uIHsKICAgIC8vLyBNb3ZlIHRoZSBmb2N1cyB0byB0aGUgbmV4dCBzZWFyY2ggbWF0Y2guCiAgICBTZWFyY2hGb2N1c05leHQsCiAgICAvLy8gTW92ZSB0aGUgZm9jdXMgdG8gdGhlIHByZXZpb3VzIHNlYXJjaCBtYXRjaC4KICAgIFNlYXJjaEZvY3VzUHJldmlvdXMsCiAgICAvLy8gQ29uZmlybSB0aGUgYWN0aXZlIHNlYXJjaC4KICAgIFNlYXJjaENvbmZpcm0sCiAgICAvLy8gQ2FuY2VsIHRoZSBhY3RpdmUgc2VhcmNoLgogICAgU2VhcmNoQ2FuY2VsLAogICAgLy8vIFJlc2V0IHRoZSBzZWFyY2ggcmVnZXguCiAgICBTZWFyY2hDbGVhciwKICAgIC8vLyBEZWxldGUgdGhlIGxhc3Qgd29yZCBpbiB0aGUgc2VhcmNoIHJlZ2V4LgogICAgU2VhcmNoRGVsZXRlV29yZCwKICAgIC8vLyBHbyB0byB0aGUgcHJldmlvdXMgcmVnZXggaW4gdGhlIHNlYXJjaCBoaXN0b3J5LgogICAgU2VhcmNoSGlzdG9yeVByZXZpb3VzLAogICAgLy8vIEdvIHRvIHRoZSBuZXh0IHJlZ2V4IGluIHRoZSBzZWFyY2ggaGlzdG9yeS4KICAgIFNlYXJjaEhpc3RvcnlOZXh0LAp9CgppbXBsIEZyb208U2VhcmNoQWN0aW9uPiBmb3IgQWN0aW9uIHsKICAgIGZuIGZyb20oYWN0aW9uOiBTZWFyY2hBY3Rpb24pIC0+IFNlbGYgewogICAgICAgIFNlbGY6OlNlYXJjaChhY3Rpb24pCiAgICB9Cn0KCiNbZGVyaXZlKERlYnVnLCBDbG9uZSwgUGFydGlhbEVxLCBFcSldCnB1YiBzdHJ1Y3QgQmluZGluZzxUPiB7CiAgICAvLy8gTW9kaWZpZXIga2V5cyByZXF1aXJlZCB0byBhY3RpdmF0ZSBiaW5kaW5nLgogICAgcHViIG1vZHM6IE1vZGlmaWVyc1N0YXRlLAoKICAgIC8vLyBTdHJpbmcgdG8gc2VuZCB0byBQVFkgaWYgbW9kcyBhbmQgbW9kZSBtYXRjaC4KICAgIHB1YiBhY3Rpb246IEFjdGlvbiwKCiAgICAvLy8gQmluZGluZyBtb2RlIHJlcXVpcmVkIHRvIGFjdGl2YXRlIGJpbmRpbmcuCiAgICBwdWIgbW9kZTogQmluZGluZ01vZGUsCgogICAgLy8vIEV4Y2x1ZGVkIGJpbmRpbmcgbW9kZXMgd2hlcmUgdGhlIGJpbmRpbmcgd29uJ3QgYmUgYWN0aXZhdGVkLgogICAgcHViIG5vdG1vZGU6IEJpbmRpbmdNb2RlLAoKICAgIC8vLyBUaGlzIHByb3BlcnR5IGlzIHVzZWQgYXMgcGFydCBvZiB0aGUgdHJpZ2dlciBkZXRlY3Rpb24gY29kZS4KICAgIC8vLwogICAgLy8vIEZvciBleGFtcGxlLCB0aGlzIG1pZ2h0IGJlIGEga2V5IGxpa2UgIkciLCBvciBhIG1vdXNlIGJ1dHRvbi4KICAgIHB1YiB0cmlnZ2VyOiBULAp9CgppbXBsPFQ6IEVxPiBCaW5kaW5nPFQ+IHsKICAgICNbaW5saW5lXQogICAgcHViIGZuIGlzX3RyaWdnZXJlZF9ieSgKICAgICAgICAmc2VsZiwKICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZSwKICAgICAgICBtb2RzOiBNb2RpZmllcnNTdGF0ZSwKICAgICAgICBpbnB1dDogJlQsCiAgICApIC0+IGJvb2wgewogICAgICAgIC8vIENoZWNrIGlucHV0IGZpcnN0IHNpbmNlIGJpbmRpbmdzIGFyZSBzdG9yZWQgaW4gb25lIGJpZyBsaXN0LiBUaGlzIGlzCiAgICAgICAgLy8gdGhlIG1vc3QgbGlrZWx5IGl0ZW0gdG8gZmFpbCBzbyBwcmlvcml0aXppbmcgaXQgaGVyZSBhbGxvd3MgbW9yZQogICAgICAgIC8vIGNoZWNrcyB0byBiZSBzaG9ydCBjaXJjdWl0ZWQuCiAgICAgICAgc2VsZi50cmlnZ2VyID09ICppbnB1dAogICAgICAgICAgICAmJiBzZWxmLm1vZHMgPT0gbW9kcwogICAgICAgICAgICAmJiBtb2RlLmNvbnRhaW5zKHNlbGYubW9kZS5jbG9uZSgpKQogICAgICAgICAgICAmJiAhbW9kZS5pbnRlcnNlY3RzKHNlbGYubm90bW9kZS5jbG9uZSgpKQogICAgfQoKICAgICNbaW5saW5lXQogICAgcHViIGZuIHRyaWdnZXJzX21hdGNoKCZzZWxmLCBiaW5kaW5nOiAmQmluZGluZzxUPikgLT4gYm9vbCB7CiAgICAgICAgLy8gQ2hlY2sgdGhlIGJpbmRpbmcncyBrZXkgYW5kIG1vZGlmaWVycy4KICAgICAgICBpZiBzZWxmLnRyaWdnZXIgIT0gYmluZGluZy50cmlnZ2VyIHx8IHNlbGYubW9kcyAhPSBiaW5kaW5nLm1vZHMgewogICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQoKICAgICAgICBsZXQgc2VsZm1vZGUgPSBpZiBzZWxmLm1vZGUuaXNfZW1wdHkoKSB7CiAgICAgICAgICAgIEJpbmRpbmdNb2RlOjphbGwoKQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHNlbGYubW9kZS5jbG9uZSgpCiAgICAgICAgfTsKICAgICAgICBsZXQgYmluZGluZ21vZGUgPSBpZiBiaW5kaW5nLm1vZGUuaXNfZW1wdHkoKSB7CiAgICAgICAgICAgIEJpbmRpbmdNb2RlOjphbGwoKQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJpbmRpbmcubW9kZS5jbG9uZSgpCiAgICAgICAgfTsKCiAgICAgICAgaWYgIXNlbGZtb2RlLmludGVyc2VjdHMoYmluZGluZ21vZGUpIHsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KCiAgICAgICAgLy8gVGhlIGJpbmRpbmdzIGFyZSBuZXZlciBhY3RpdmUgYXQgdGhlIHNhbWUgdGltZSB3aGVuIHRoZSByZXF1aXJlZCBtb2RlcyBvZiBvbmUgYmluZGluZwogICAgICAgIC8vIGFyZSBwYXJ0IG9mIHRoZSBmb3JiaWRkZW4gYmluZGluZ3Mgb2YgdGhlIG90aGVyLgogICAgICAgIGlmIHNlbGYubW9kZS5pbnRlcnNlY3RzKGJpbmRpbmcubm90bW9kZS5jbG9uZSgpKQogICAgICAgICAgICB8fCBiaW5kaW5nLm1vZGUuaW50ZXJzZWN0cyhzZWxmLm5vdG1vZGUuY2xvbmUoKSkKICAgICAgICB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIHRydWUKICAgIH0KfQoKI1tkZXJpdmUoQ2xvbmUsIERlYnVnLCBFcSwgUGFydGlhbEVxLCBIYXNoKV0KcHViIGVudW0gQmluZGluZ0tleSB7CiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBTY2FuY29kZShQaHlzaWNhbEtleSksCiAgICBLZXljb2RlIHsKICAgICAgICBrZXk6IEtleSwKICAgICAgICBsb2NhdGlvbjogS2V5TG9jYXRpb24sCiAgICB9LAp9CgpwdWIgdHlwZSBLZXlCaW5kaW5nID0gQmluZGluZzxCaW5kaW5nS2V5PjsKcHViIHR5cGUgS2V5QmluZGluZ3MgPSBWZWM8S2V5QmluZGluZz47CgovLy8gQmluZGluZ3MgdGhhdCBhcmUgdHJpZ2dlcmVkIGJ5IGEgbW91c2UgYnV0dG9uLgpwdWIgdHlwZSBNb3VzZUJpbmRpbmcgPSBCaW5kaW5nPE1vdXNlQnV0dG9uPjsKCmJpdGZsYWdzISB7CiAgICAvLy8gTW9kZXMgYXZhaWxhYmxlIGZvciBrZXkgYmluZGluZ3MuCiAgICAjW2Rlcml2ZShDbG9uZSwgRGVidWcsIEVxLCBQYXJ0aWFsRXEpXQogICAgcHViIHN0cnVjdCBCaW5kaW5nTW9kZTogdTggewogICAgICAgIGNvbnN0IEFQUF9DVVJTT1IgICAgICAgICAgPSAwYjAwMDBfMDAwMTsKICAgICAgICBjb25zdCBBUFBfS0VZUEFEICAgICAgICAgID0gMGIwMDAwXzAwMTA7CiAgICAgICAgY29uc3QgQUxUX1NDUkVFTiAgICAgICAgICA9IDBiMDAwMF8wMTAwOwogICAgICAgIGNvbnN0IFZJICAgICAgICAgICAgICAgICAgPSAwYjAwMDBfMTAwMDsKICAgICAgICBjb25zdCBTRUFSQ0ggICAgICAgICAgICAgID0gMGIwMDAxXzAwMDA7CiAgICAgICAgY29uc3QgRElTQU1CSUdVQVRFX0tFWVMgICA9IDBiMDAxMF8wMDAwOwogICAgICAgIGNvbnN0IEFMTF9LRVlTX0FTX0VTQyAgICAgPSAwYjAxMDBfMDAwMDsKICAgIH0KfQoKaW1wbCBCaW5kaW5nTW9kZSB7CiAgICBwdWIgZm4gbmV3KG1vZGU6ICZNb2RlLCBzZWFyY2g6IGJvb2wpIC0+IEJpbmRpbmdNb2RlIHsKICAgICAgICBsZXQgbXV0IGJpbmRpbmdfbW9kZSA9IEJpbmRpbmdNb2RlOjplbXB0eSgpOwogICAgICAgIGJpbmRpbmdfbW9kZS5zZXQoQmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIG1vZGUuY29udGFpbnMoTW9kZTo6QVBQX0NVUlNPUikpOwogICAgICAgIGJpbmRpbmdfbW9kZS5zZXQoQmluZGluZ01vZGU6OkFQUF9LRVlQQUQsIG1vZGUuY29udGFpbnMoTW9kZTo6QVBQX0tFWVBBRCkpOwogICAgICAgIGJpbmRpbmdfbW9kZS5zZXQoQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sIG1vZGUuY29udGFpbnMoTW9kZTo6QUxUX1NDUkVFTikpOwogICAgICAgIGJpbmRpbmdfbW9kZS5zZXQoQmluZGluZ01vZGU6OlNFQVJDSCwgc2VhcmNoKTsKICAgICAgICBiaW5kaW5nX21vZGUuc2V0KAogICAgICAgICAgICBCaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVMsCiAgICAgICAgICAgIG1vZGUuY29udGFpbnMoTW9kZTo6RElTQU1CSUdVQVRFX0VTQ19DT0RFUyksCiAgICAgICAgKTsKICAgICAgICBiaW5kaW5nX21vZGUuc2V0KAogICAgICAgICAgICBCaW5kaW5nTW9kZTo6QUxMX0tFWVNfQVNfRVNDLAogICAgICAgICAgICBtb2RlLmNvbnRhaW5zKE1vZGU6OlJFUE9SVF9BTExfS0VZU19BU19FU0MpLAogICAgICAgICk7CiAgICAgICAgYmluZGluZ19tb2RlLnNldChCaW5kaW5nTW9kZTo6VkksIG1vZGUuY29udGFpbnMoTW9kZTo6VkkpKTsKICAgICAgICBiaW5kaW5nX21vZGUKICAgIH0KfQoKI1tkZXJpdmUoRGVidWcsIENsb25lLCBFcSwgUGFydGlhbEVxKV0KI1thbGxvdyh1bnVzZWQpXQpwdWIgZW51bSBQcm9ncmFtIHsKICAgIEp1c3QoU3RyaW5nKSwKICAgIFdpdGhBcmdzIHsgcHJvZ3JhbTogU3RyaW5nLCBhcmdzOiBWZWM8U3RyaW5nPiB9LAp9CgppbXBsIFByb2dyYW0gewogICAgcHViIGZuIHByb2dyYW0oJnNlbGYpIC0+ICZzdHIgewogICAgICAgIG1hdGNoIHNlbGYgewogICAgICAgICAgICBQcm9ncmFtOjpKdXN0KHByb2dyYW0pID0+IHByb2dyYW0sCiAgICAgICAgICAgIFByb2dyYW06OldpdGhBcmdzIHsgcHJvZ3JhbSwgLi4gfSA9PiBwcm9ncmFtLAogICAgICAgIH0KICAgIH0KCiAgICBwdWIgZm4gYXJncygmc2VsZikgLT4gJltTdHJpbmddIHsKICAgICAgICBtYXRjaCBzZWxmIHsKICAgICAgICAgICAgUHJvZ3JhbTo6SnVzdChfKSA9PiAmW10sCiAgICAgICAgICAgIFByb2dyYW06OldpdGhBcmdzIHsgYXJncywgLi4gfSA9PiBhcmdzLAogICAgICAgIH0KICAgIH0KfQoKaW1wbCBGcm9tPFN0cmluZz4gZm9yIEFjdGlvbiB7CiAgICBmbiBmcm9tKGFjdGlvbjogU3RyaW5nKSAtPiBBY3Rpb24gewogICAgICAgIGxldCBhY3Rpb24gPSBhY3Rpb24udG9fbG93ZXJjYXNlKCk7CgogICAgICAgIGxldCBhY3Rpb25fZnJvbV9zdHJpbmcgPSBtYXRjaCBhY3Rpb24uYXNfc3RyKCkgewogICAgICAgICAgICAicGFzdGUiID0+IFNvbWUoQWN0aW9uOjpQYXN0ZSksCiAgICAgICAgICAgICJxdWl0IiA9PiBTb21lKEFjdGlvbjo6UXVpdCksCiAgICAgICAgICAgICJjb3B5IiA9PiBTb21lKEFjdGlvbjo6Q29weSksCiAgICAgICAgICAgICJzZWFyY2hmb3J3YXJkIiA9PiBTb21lKEFjdGlvbjo6U2VhcmNoRm9yd2FyZCksCiAgICAgICAgICAgICJzZWFyY2hiYWNrd2FyZCIgPT4gU29tZShBY3Rpb246OlNlYXJjaEJhY2t3YXJkKSwKICAgICAgICAgICAgInNlYXJjaGNvbmZpcm0iID0+IFNvbWUoQWN0aW9uOjpTZWFyY2goU2VhcmNoQWN0aW9uOjpTZWFyY2hDb25maXJtKSksCiAgICAgICAgICAgICJzZWFyY2hjYW5jZWwiID0+IFNvbWUoQWN0aW9uOjpTZWFyY2goU2VhcmNoQWN0aW9uOjpTZWFyY2hDYW5jZWwpKSwKICAgICAgICAgICAgInNlYXJjaGNsZWFyIiA9PiBTb21lKEFjdGlvbjo6U2VhcmNoKFNlYXJjaEFjdGlvbjo6U2VhcmNoQ2xlYXIpKSwKICAgICAgICAgICAgInNlYXJjaGZvY3VzbmV4dCIgPT4gU29tZShBY3Rpb246OlNlYXJjaChTZWFyY2hBY3Rpb246OlNlYXJjaEZvY3VzTmV4dCkpLAogICAgICAgICAgICAic2VhcmNoZm9jdXNwcmV2aW91cyIgPT4gewogICAgICAgICAgICAgICAgU29tZShBY3Rpb246OlNlYXJjaChTZWFyY2hBY3Rpb246OlNlYXJjaEZvY3VzUHJldmlvdXMpKQogICAgICAgICAgICB9CiAgICAgICAgICAgICJzZWFyY2hkZWxldGV3b3JkIiA9PiBTb21lKEFjdGlvbjo6U2VhcmNoKFNlYXJjaEFjdGlvbjo6U2VhcmNoRGVsZXRlV29yZCkpLAogICAgICAgICAgICAic2VhcmNoaGlzdG9yeW5leHQiID0+IFNvbWUoQWN0aW9uOjpTZWFyY2goU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dCkpLAogICAgICAgICAgICAic2VhcmNoaGlzdG9yeXByZXZpb3VzIiA9PiB7CiAgICAgICAgICAgICAgICBTb21lKEFjdGlvbjo6U2VhcmNoKFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeVByZXZpb3VzKSkKICAgICAgICAgICAgfQogICAgICAgICAgICAiY2xlYXJoaXN0b3J5IiA9PiBTb21lKEFjdGlvbjo6Q2xlYXJIaXN0b3J5KSwKICAgICAgICAgICAgInJlc2V0Zm9udHNpemUiID0+IFNvbWUoQWN0aW9uOjpSZXNldEZvbnRTaXplKSwKICAgICAgICAgICAgImluY3JlYXNlZm9udHNpemUiID0+IFNvbWUoQWN0aW9uOjpJbmNyZWFzZUZvbnRTaXplKSwKICAgICAgICAgICAgImRlY3JlYXNlZm9udHNpemUiID0+IFNvbWUoQWN0aW9uOjpEZWNyZWFzZUZvbnRTaXplKSwKICAgICAgICAgICAgImNyZWF0ZXdpbmRvdyIgPT4gU29tZShBY3Rpb246OldpbmRvd0NyZWF0ZU5ldyksCiAgICAgICAgICAgICJjcmVhdGV0YWIiID0+IFNvbWUoQWN0aW9uOjpUYWJDcmVhdGVOZXcpLAogICAgICAgICAgICAiY2xvc2V0YWIiID0+IFNvbWUoQWN0aW9uOjpUYWJDbG9zZUN1cnJlbnQpLAogICAgICAgICAgICAiY2xvc2VjdXJyZW50dGFib3JzcGxpdCIgPT4gU29tZShBY3Rpb246OkNsb3NlQ3VycmVudFNwbGl0T3JUYWIpLAogICAgICAgICAgICAiY2xvc2V1bmZvY3VzZWR0YWJzIiA9PiBTb21lKEFjdGlvbjo6VGFiQ2xvc2VVbmZvY3VzZWQpLAogICAgICAgICAgICAib3BlbmNvbmZpZ2VkaXRvciIgPT4gU29tZShBY3Rpb246OkNvbmZpZ0VkaXRvciksCiAgICAgICAgICAgICJzZWxlY3RwcmV2dGFiIiA9PiBTb21lKEFjdGlvbjo6U2VsZWN0UHJldlRhYiksCiAgICAgICAgICAgICJzZWxlY3RuZXh0dGFiIiA9PiBTb21lKEFjdGlvbjo6U2VsZWN0TmV4dFRhYiksCiAgICAgICAgICAgICJzZWxlY3RsYXN0dGFiIiA9PiBTb21lKEFjdGlvbjo6U2VsZWN0TGFzdFRhYiksCiAgICAgICAgICAgICJyZWNlaXZlY2hhciIgPT4gU29tZShBY3Rpb246OlJlY2VpdmVDaGFyKSwKICAgICAgICAgICAgInNjcm9sbGhhbGZwYWdldXAiID0+IFNvbWUoQWN0aW9uOjpTY3JvbGxIYWxmUGFnZVVwKSwKICAgICAgICAgICAgInNjcm9sbGhhbGZwYWdlZG93biIgPT4gU29tZShBY3Rpb246OlNjcm9sbEhhbGZQYWdlRG93biksCiAgICAgICAgICAgICJzY3JvbGx0b3RvcCIgPT4gU29tZShBY3Rpb246OlNjcm9sbFRvVG9wKSwKICAgICAgICAgICAgInNjcm9sbHRvYm90dG9tIiA9PiBTb21lKEFjdGlvbjo6U2Nyb2xsVG9Cb3R0b20pLAogICAgICAgICAgICAic3BsaXRyaWdodCIgPT4gU29tZShBY3Rpb246OlNwbGl0UmlnaHQpLAogICAgICAgICAgICAic3BsaXRkb3duIiA9PiBTb21lKEFjdGlvbjo6U3BsaXREb3duKSwKICAgICAgICAgICAgInNlbGVjdG5leHRzcGxpdCIgPT4gU29tZShBY3Rpb246OlNlbGVjdE5leHRTcGxpdCksCiAgICAgICAgICAgICJzZWxlY3RwcmV2c3BsaXQiID0+IFNvbWUoQWN0aW9uOjpTZWxlY3RQcmV2U3BsaXQpLAogICAgICAgICAgICAidG9nZ2xldmltb2RlIiA9PiBTb21lKEFjdGlvbjo6VG9nZ2xlVmlNb2RlKSwKICAgICAgICAgICAgInRvZ2dsZWZ1bGxzY3JlZW4iID0+IFNvbWUoQWN0aW9uOjpUb2dnbGVGdWxsc2NyZWVuKSwKICAgICAgICAgICAgIm5vbmUiID0+IFNvbWUoQWN0aW9uOjpOb25lKSwKICAgICAgICAgICAgXyA9PiBOb25lLAogICAgICAgIH07CgogICAgICAgIGlmIGFjdGlvbl9mcm9tX3N0cmluZy5pc19zb21lKCkgewogICAgICAgICAgICByZXR1cm4gYWN0aW9uX2Zyb21fc3RyaW5nLnVud3JhcF9vcihBY3Rpb246Ok5vbmUpOwogICAgICAgIH0KCiAgICAgICAgbGV0IHJlID0gcmVnZXg6OlJlZ2V4OjpuZXcociJzZWxlY3R0YWJcKChbXigpXSspXCkiKS51bndyYXAoKTsKICAgICAgICBmb3IgY2FwdHVyZSBpbiByZS5jYXB0dXJlc19pdGVyKCZhY3Rpb24pIHsKICAgICAgICAgICAgaWYgbGV0IFNvbWUobWF0Y2hlZCkgPSBjYXB0dXJlLmdldCgxKSB7CiAgICAgICAgICAgICAgICBsZXQgbWF0Y2hlZF9zdHJpbmcgPSBtYXRjaGVkLmFzX3N0cigpLnRvX3N0cmluZygpOwogICAgICAgICAgICAgICAgbGV0IHBhcnNlZF9tYXRjaGVkX3N0cmluZzogdXNpemUgPSBtYXRjaGVkX3N0cmluZy5wYXJzZSgpLnVud3JhcF9vcigwKTsKICAgICAgICAgICAgICAgIHJldHVybiBBY3Rpb246OlNlbGVjdFRhYihwYXJzZWRfbWF0Y2hlZF9zdHJpbmcpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBsZXQgcmUgPSByZWdleDo6UmVnZXg6Om5ldyhyInJ1blwoKFteKCldKylcKSIpLnVud3JhcCgpOwogICAgICAgIGZvciBjYXB0dXJlIGluIHJlLmNhcHR1cmVzX2l0ZXIoJmFjdGlvbikgewogICAgICAgICAgICBpZiBsZXQgU29tZShtYXRjaGVkKSA9IGNhcHR1cmUuZ2V0KDEpIHsKICAgICAgICAgICAgICAgIGxldCBtYXRjaGVkX3N0cmluZyA9IG1hdGNoZWQuYXNfc3RyKCkudG9fc3RyaW5nKCk7CiAgICAgICAgICAgICAgICBpZiBtYXRjaGVkX3N0cmluZy5jb250YWlucygnICcpIHsKICAgICAgICAgICAgICAgICAgICBsZXQgbXV0IHZlY19wcm9ncmFtX3dpdGhfYXJnczogVmVjPFN0cmluZz4gPQogICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVkX3N0cmluZy5zcGxpdCgnICcpLm1hcCh8c3wgcy50b19zdHJpbmcoKSkuY29sbGVjdCgpOwogICAgICAgICAgICAgICAgICAgIGlmIHZlY19wcm9ncmFtX3dpdGhfYXJncy5pc19lbXB0eSgpIHsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICBsZXQgcHJvZ3JhbSA9IHZlY19wcm9ncmFtX3dpdGhfYXJnc1swXS50b19zdHJpbmcoKTsKICAgICAgICAgICAgICAgICAgICB2ZWNfcHJvZ3JhbV93aXRoX2FyZ3MucmVtb3ZlKDApOwoKICAgICAgICAgICAgICAgICAgICByZXR1cm4gQWN0aW9uOjpSdW4oUHJvZ3JhbTo6V2l0aEFyZ3MgewogICAgICAgICAgICAgICAgICAgICAgICBwcm9ncmFtLAogICAgICAgICAgICAgICAgICAgICAgICBhcmdzOiB2ZWNfcHJvZ3JhbV93aXRoX2FyZ3MsCiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICAgIHJldHVybiBBY3Rpb246OlJ1bihQcm9ncmFtOjpKdXN0KG1hdGNoZWRfc3RyaW5nKSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGxldCByZSA9IHJlZ2V4OjpSZWdleDo6bmV3KHIic2Nyb2xsXCgoW14oKV0rKVwpIikudW53cmFwKCk7CiAgICAgICAgZm9yIGNhcHR1cmUgaW4gcmUuY2FwdHVyZXNfaXRlcigmYWN0aW9uKSB7CiAgICAgICAgICAgIGlmIGxldCBTb21lKG1hdGNoZWQpID0gY2FwdHVyZS5nZXQoMSkgewogICAgICAgICAgICAgICAgbGV0IG1hdGNoZWRfc3RyaW5nID0gbWF0Y2hlZC5hc19zdHIoKS50b19zdHJpbmcoKTsKICAgICAgICAgICAgICAgIGxldCBwYXJzZWRfbWF0Y2hlZF9zdHJpbmc6IGkzMiA9IG1hdGNoZWRfc3RyaW5nLnBhcnNlKCkudW53cmFwX29yKDEpOwogICAgICAgICAgICAgICAgcmV0dXJuIEFjdGlvbjo6U2Nyb2xsKHBhcnNlZF9tYXRjaGVkX3N0cmluZyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIEFjdGlvbjo6Tm9uZQogICAgfQp9CgojW2Rlcml2ZShEZWJ1ZywgQ2xvbmUsIFBhcnRpYWxFcSwgRXEpXQpwdWIgZW51bSBBY3Rpb24gewogICAgLy8vIFdyaXRlIGFuIGVzY2FwZSBzZXF1ZW5jZS4KICAgIEVzYyhTdHJpbmcpLAoKICAgIC8vLyBSdW4gZ2l2ZW4gY29tbWFuZC4KICAgIFJ1bihQcm9ncmFtKSwKCiAgICAvLy8gU2Nyb2xsCiAgICBTY3JvbGwoaTMyKSwKCiAgICAvLyBSZWdleCBrZXlib2FyZCBoaW50cy4KICAgIC8vIEhpbnQoSGludCksCgogICAgLy8gTW92ZSB2aSBtb2RlIGN1cnNvci4KICAgIFZpTW90aW9uKFZpTW90aW9uKSwKCiAgICAvLyBQZXJmb3JtIHZpIG1vZGUgYWN0aW9uLgogICAgVmkoVmlBY3Rpb24pLAogICAgLy8vIFBlcmZvcm0gbW91c2UgYmluZGluZyBleGNsdXNpdmUgYWN0aW9uLgogICAgTW91c2UoTW91c2VBY3Rpb24pLAoKICAgIC8vLyBQYXN0ZSBjb250ZW50cyBvZiBzeXN0ZW0gY2xpcGJvYXJkLgogICAgUGFzdGUsCgogICAgLy8vIFN0b3JlIGN1cnJlbnQgc2VsZWN0aW9uIGludG8gY2xpcGJvYXJkLgogICAgQ29weSwKCiAgICAjW2NmZyhub3QoYW55KHRhcmdldF9vcyA9ICJtYWNvcyIsIHdpbmRvd3MpKSldCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICAvLy8gU3RvcmUgY3VycmVudCBzZWxlY3Rpb24gaW50byBzZWxlY3Rpb24gYnVmZmVyLgogICAgQ29weVNlbGVjdGlvbiwKCiAgICAvLy8gUGFzdGUgY29udGVudHMgb2Ygc2VsZWN0aW9uIGJ1ZmZlci4KICAgIFBhc3RlU2VsZWN0aW9uLAoKICAgIC8vLyBJbmNyZWFzZSBmb250IHNpemUuCiAgICBJbmNyZWFzZUZvbnRTaXplLAoKICAgIC8vLyBEZWNyZWFzZSBmb250IHNpemUuCiAgICBEZWNyZWFzZUZvbnRTaXplLAoKICAgIC8vLyBSZXNldCBmb250IHNpemUgdG8gdGhlIGNvbmZpZyB2YWx1ZS4KICAgIFJlc2V0Rm9udFNpemUsCgogICAgLy8vIFNjcm9sbCBleGFjdGx5IG9uZSBwYWdlIHVwLgogICAgU2Nyb2xsUGFnZVVwLAoKICAgIC8vLyBTY3JvbGwgZXhhY3RseSBvbmUgcGFnZSBkb3duLgogICAgU2Nyb2xsUGFnZURvd24sCgogICAgLy8vIFNjcm9sbCBoYWxmIGEgcGFnZSB1cC4KICAgIFNjcm9sbEhhbGZQYWdlVXAsCgogICAgLy8vIFNjcm9sbCBoYWxmIGEgcGFnZSBkb3duLgogICAgU2Nyb2xsSGFsZlBhZ2VEb3duLAoKICAgIC8vLyBTY3JvbGwgYWxsIHRoZSB3YXkgdG8gdGhlIHRvcC4KICAgIFNjcm9sbFRvVG9wLAoKICAgIC8vLyBTY3JvbGwgYWxsIHRoZSB3YXkgdG8gdGhlIGJvdHRvbS4KICAgIFNjcm9sbFRvQm90dG9tLAoKICAgIC8vLyBDbGVhciB0aGUgZGlzcGxheSBidWZmZXIocykgdG8gcmVtb3ZlIGhpc3RvcnkuCiAgICBDbGVhckhpc3RvcnksCgogICAgLy8vIEhpZGUgdGhlIFJpbyB3aW5kb3cuCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBIaWRlLAoKICAgIC8vLyBIaWRlIGFsbCB3aW5kb3dzIG90aGVyIHRoYW4gUmlvIG9uIG1hY09TLgogICAgI1tjZmcodGFyZ2V0X29zID0gIm1hY29zIildCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBIaWRlT3RoZXJBcHBsaWNhdGlvbnMsCgogICAgLy8vIE1pbmltaXplIHRoZSBSaW8gd2luZG93LgogICAgI1thbGxvdyhkZWFkX2NvZGUpXQogICAgTWluaW1pemUsCgogICAgLy8vIFF1aXQgUmlvLgogICAgUXVpdCwKCiAgICAvLy8gQ2xlYXIgd2FybmluZyBhbmQgZXJyb3Igbm90aWNlcy4KICAgIENsZWFyTG9nTm90aWNlLAoKICAgIC8vLyBTcGF3biBhIG5ldyBpbnN0YW5jZSBvZiBSaW8uCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBTcGF3bk5ld0luc3RhbmNlLAoKICAgIC8vLyBDcmVhdGUgYSBuZXcgUmlvIHdpbmRvdy4KICAgICNbYWxsb3coZGVhZF9jb2RlKV0KICAgIFdpbmRvd0NyZWF0ZU5ldywKCiAgICAvLy8gQ3JlYXRlIGNvbmZpZyBlZGl0b3IuCiAgICBDb25maWdFZGl0b3IsCgogICAgLy8vIENyZWF0ZSBhIG5ldyBSaW8gdGFiLgogICAgVGFiQ3JlYXRlTmV3LAoKICAgIC8vLyBTd2l0Y2ggdG8gbmV4dCB0YWIuCiAgICBTZWxlY3ROZXh0VGFiLAoKICAgIC8vLyBTd2l0Y2ggdG8gcHJldiB0YWIuCiAgICBTZWxlY3RQcmV2VGFiLAoKICAgIC8vLyBDbG9zZSB0YWIuCiAgICBUYWJDbG9zZUN1cnJlbnQsCgogICAgQ2xvc2VDdXJyZW50U3BsaXRPclRhYiwKCiAgICAvLy8gQ2xvc2UgYWxsIG90aGVyIHRhYnMgKGxlYXZlIG9ubHkgdGhlIGN1cnJlbnQgdGFiKS4KICAgIFRhYkNsb3NlVW5mb2N1c2VkLAoKICAgIC8vLyBUb2dnbGUgZnVsbHNjcmVlbi4KICAgICNbYWxsb3coZGVhZF9jb2RlKV0KICAgIFRvZ2dsZUZ1bGxzY3JlZW4sCgogICAgLy8vIFRvZ2dsZSBtYXhpbWl6ZWQuCiAgICAjW2FsbG93KGRlYWRfY29kZSldCiAgICBUb2dnbGVNYXhpbWl6ZWQsCgogICAgLy8vIFRvZ2dsZSBzaW1wbGUgZnVsbHNjcmVlbiBvbiBtYWNPUy4KICAgICNbY2ZnKHRhcmdldF9vcyA9ICJtYWNvcyIpXQogICAgI1thbGxvdyhkZWFkX2NvZGUpXQogICAgVG9nZ2xlU2ltcGxlRnVsbHNjcmVlbiwKCiAgICAvLy8gQ2xlYXIgYWN0aXZlIHNlbGVjdGlvbi4KICAgIENsZWFyU2VsZWN0aW9uLAoKICAgIC8vLyBUb2dnbGUgdmkgbW9kZS4KICAgIFRvZ2dsZVZpTW9kZSwKCiAgICAvLyBUYWIgc2VsZWN0aW9ucwogICAgU2VsZWN0VGFiKHVzaXplKSwKICAgIFNlbGVjdExhc3RUYWIsCgogICAgU2VhcmNoKFNlYXJjaEFjdGlvbiksCiAgICAvLy8gU3RhcnQgYSBmb3J3YXJkIGJ1ZmZlciBzZWFyY2guCiAgICBTZWFyY2hGb3J3YXJkLAoKICAgIC8vLyBTdGFydCBhIGJhY2t3YXJkIGJ1ZmZlciBzZWFyY2guCiAgICBTZWFyY2hCYWNrd2FyZCwKCiAgICAvLy8gU3BsaXQgaG9yaXpvbnRhbGx5CiAgICBTcGxpdFJpZ2h0LAoKICAgIC8vLyBTcGxpdCB2ZXJ0aWNhbGx5CiAgICBTcGxpdERvd24sCgogICAgU2VsZWN0TmV4dFNwbGl0LAogICAgU2VsZWN0UHJldlNwbGl0LAoKICAgIC8vLyBBbGxvdyByZWNlaXZpbmcgY2hhciBpbnB1dC4KICAgIFJlY2VpdmVDaGFyLAoKICAgIC8vLyBObyBhY3Rpb24uCiAgICBOb25lLAp9CgppbXBsIEZyb208JidzdGF0aWMgc3RyPiBmb3IgQWN0aW9uIHsKICAgIGZuIGZyb20oczogJidzdGF0aWMgc3RyKSAtPiBBY3Rpb24gewogICAgICAgIEFjdGlvbjo6RXNjKHMuaW50bygpKQogICAgfQp9CgppbXBsIEZyb208VmlNb3Rpb24+IGZvciBBY3Rpb24gewogICAgZm4gZnJvbShtb3Rpb246IFZpTW90aW9uKSAtPiBTZWxmIHsKICAgICAgICBTZWxmOjpWaU1vdGlvbihtb3Rpb24pCiAgICB9Cn0KCmltcGwgRnJvbTxWaUFjdGlvbj4gZm9yIEFjdGlvbiB7CiAgICBmbiBmcm9tKGFjdGlvbjogVmlBY3Rpb24pIC0+IFNlbGYgewogICAgICAgIFNlbGY6OlZpKGFjdGlvbikKICAgIH0KfQoKLy8vIFZpIG1vZGUgc3BlY2lmaWMgYWN0aW9ucy4KI1tkZXJpdmUoRGVidWcsIENvcHksIENsb25lLCBQYXJ0aWFsRXEsIEVxKV0KcHViIGVudW0gVmlBY3Rpb24gewogICAgLy8vIFRvZ2dsZSBub3JtYWwgdmkgc2VsZWN0aW9uLgogICAgVG9nZ2xlTm9ybWFsU2VsZWN0aW9uLAogICAgLy8vIFRvZ2dsZSBsaW5lIHZpIHNlbGVjdGlvbi4KICAgIFRvZ2dsZUxpbmVTZWxlY3Rpb24sCiAgICAvLy8gVG9nZ2xlIGJsb2NrIHZpIHNlbGVjdGlvbi4KICAgIFRvZ2dsZUJsb2NrU2VsZWN0aW9uLAogICAgLy8vIFRvZ2dsZSBzZW1hbnRpYyB2aSBzZWxlY3Rpb24uCiAgICBUb2dnbGVTZW1hbnRpY1NlbGVjdGlvbiwKICAgIC8vLyBDZW50ZXJzIHRoZSBzY3JlZW4gYXJvdW5kIHRoZSB2aSBtb2RlIGN1cnNvci4KICAgIENlbnRlckFyb3VuZFZpQ3Vyc29yLAp9CgptYWNyb19ydWxlcyEgYmluZGluZ3MgewogICAgKAogICAgICAgICR0eTppZGVudDsKICAgICAgICAkKAogICAgICAgICAgICAka2V5OmV4cHIKICAgICAgICAgICAgJCg9PiRsb2NhdGlvbjpleHByKT8KICAgICAgICAgICAgJCgsJG1vZHM6ZXhwcikqCiAgICAgICAgICAgICQoLCskbW9kZTpleHByKSoKICAgICAgICAgICAgJCgsfiRub3Rtb2RlOmV4cHIpKgogICAgICAgICAgICA7JGFjdGlvbjpleHByCiAgICAgICAgKTsqCiAgICAgICAgJCg7KSoKICAgICkgPT4ge3sKICAgICAgICBsZXQgbXV0IHYgPSBWZWM6Om5ldygpOwoKICAgICAgICAkKAogICAgICAgICAgICBsZXQgbXV0IF9tb2RzID0gTW9kaWZpZXJzU3RhdGU6OmVtcHR5KCk7CiAgICAgICAgICAgICQoX21vZHMgPSAkbW9kczspKgogICAgICAgICAgICBsZXQgbXV0IF9tb2RlID0gQmluZGluZ01vZGU6OmVtcHR5KCk7CiAgICAgICAgICAgICQoX21vZGUuaW5zZXJ0KCRtb2RlKTspKgogICAgICAgICAgICBsZXQgbXV0IF9ub3Rtb2RlID0gQmluZGluZ01vZGU6OmVtcHR5KCk7CiAgICAgICAgICAgICQoX25vdG1vZGUuaW5zZXJ0KCRub3Rtb2RlKTspKgoKICAgICAgICAgICAgdi5wdXNoKCR0eSB7CiAgICAgICAgICAgICAgICB0cmlnZ2VyOiB0cmlnZ2VyISgkdHksICRrZXksICQoJGxvY2F0aW9uKT8pLAogICAgICAgICAgICAgICAgbW9kczogX21vZHMsCiAgICAgICAgICAgICAgICBtb2RlOiBfbW9kZSwKICAgICAgICAgICAgICAgIG5vdG1vZGU6IF9ub3Rtb2RlLAogICAgICAgICAgICAgICAgYWN0aW9uOiAkYWN0aW9uLmludG8oKSwKICAgICAgICAgICAgfSk7CiAgICAgICAgKSoKCiAgICAgICAgdgogICAgfX07Cn0KCm1hY3JvX3J1bGVzISB0cmlnZ2VyIHsKICAgIChLZXlCaW5kaW5nLCAka2V5OmxpdGVyYWwsICRsb2NhdGlvbjpleHByKSA9PiB7ewogICAgICAgIEJpbmRpbmdLZXk6OktleWNvZGUgewogICAgICAgICAgICBrZXk6IENoYXJhY3Rlcigka2V5LmludG8oKSksCiAgICAgICAgICAgIGxvY2F0aW9uOiAkbG9jYXRpb24sCiAgICAgICAgfQogICAgfX07CiAgICAoS2V5QmluZGluZywgJGtleTpsaXRlcmFsLCkgPT4ge3sKICAgICAgICBCaW5kaW5nS2V5OjpLZXljb2RlIHsKICAgICAgICAgICAga2V5OiBDaGFyYWN0ZXIoJGtleS5pbnRvKCkpLAogICAgICAgICAgICBsb2NhdGlvbjogS2V5TG9jYXRpb246OlN0YW5kYXJkLAogICAgICAgIH0KICAgIH19OwogICAgKEtleUJpbmRpbmcsICRrZXk6ZXhwciwpID0+IHt7CiAgICAgICAgQmluZGluZ0tleTo6S2V5Y29kZSB7CiAgICAgICAgICAgIGtleTogJGtleSwKICAgICAgICAgICAgbG9jYXRpb246IEtleUxvY2F0aW9uOjpTdGFuZGFyZCwKICAgICAgICB9CiAgICB9fTsKICAgICgkdHk6aWRlbnQsICRrZXk6ZXhwciwpID0+IHt7CiAgICAgICAgJGtleQogICAgfX07Cn0KCnB1YiBmbiBkZWZhdWx0X21vdXNlX2JpbmRpbmdzKCkgLT4gVmVjPE1vdXNlQmluZGluZz4gewogICAgYmluZGluZ3MhKAogICAgICAgIE1vdXNlQmluZGluZzsKICAgICAgICBNb3VzZUJ1dHRvbjo6UmlnaHQ7ICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1vdXNlQWN0aW9uOjpFeHBhbmRTZWxlY3Rpb247CiAgICAgICAgTW91c2VCdXR0b246OlJpZ2h0LCAgIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyBNb3VzZUFjdGlvbjo6RXhwYW5kU2VsZWN0aW9uOwogICAgICAgIE1vdXNlQnV0dG9uOjpNaWRkbGUsIH5CaW5kaW5nTW9kZTo6Vkk7ICAgICAgICAgQWN0aW9uOjpQYXN0ZVNlbGVjdGlvbjsKICAgICkKfQoKcHViIGZuIGRlZmF1bHRfa2V5X2JpbmRpbmdzKAogICAgdW5wcm9jZXNzZWRfY29uZmlnX2tleV9iaW5kaW5nczogVmVjPENvbmZpZ0tleUJpbmRpbmc+LAogICAgdXNlX25hdmlnYXRpb25fa2V5X2JpbmRpbmdzOiBib29sLAogICAgdXNlX3NwbGl0czogYm9vbCwKICAgIGNvbmZpZ19rZXlib2FyZDogQ29uZmlnS2V5Ym9hcmQsCikgLT4gVmVjPEtleUJpbmRpbmc+IHsKICAgIGxldCBtdXQgYmluZGluZ3MgPSBiaW5kaW5ncyEoCiAgICAgICAgS2V5QmluZGluZzsKICAgICAgICBLZXk6Ok5hbWVkKENvcHkpOyAgQWN0aW9uOjpDb3B5OwogICAgICAgIEtleTo6TmFtZWQoQ29weSksICArQmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkNsZWFyU2VsZWN0aW9uOwogICAgICAgIEtleTo6TmFtZWQoUGFzdGUpLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlBhc3RlOwogICAgICAgIEtleTo6Q2hhcmFjdGVyKCJsIi5pbnRvKCkpLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgQWN0aW9uOjpDbGVhckxvZ05vdGljZTsKICAgICAgICAibCIsICBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpFc2MoIlx4MGMiLmludG8oKSk7CiAgICAgICAgS2V5OjpOYW1lZChUYWIpLCAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkVzYygiXHgxYltaIi5pbnRvKCkpOwogICAgICAgIEtleTo6TmFtZWQoSG9tZSksICAgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6QUxUX1NDUkVFTjsgQWN0aW9uOjpTY3JvbGxUb1RvcDsKICAgICAgICBLZXk6Ok5hbWVkKEVuZCksICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OkFMVF9TQ1JFRU47IEFjdGlvbjo6U2Nyb2xsVG9Cb3R0b207CiAgICAgICAgS2V5OjpOYW1lZChQYWdlVXApLCAgIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOOyBBY3Rpb246OlNjcm9sbFBhZ2VVcDsKICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VEb3duKSwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OkFMVF9TQ1JFRU47IEFjdGlvbjo6U2Nyb2xsUGFnZURvd247CiAgICAgICAgS2V5OjpOYW1lZChIb21lKSwgICtCaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgQWN0aW9uOjpFc2MoIlx4MWJPSCIuaW50bygpKTsKICAgICAgICBLZXk6Ok5hbWVkKEVuZCksICAgK0JpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICBBY3Rpb246OkVzYygiXHgxYk9GIi5pbnRvKCkpOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dVcCksICAgICtCaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgQWN0aW9uOjpFc2MoIlx4MWJPQSIuaW50bygpKTsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93RG93biksICArQmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgIEFjdGlvbjo6RXNjKCJceDFiT0IiLmludG8oKSk7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd1JpZ2h0KSwgK0JpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICBBY3Rpb246OkVzYygiXHgxYk9DIi5pbnRvKCkpOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dMZWZ0KSwgICtCaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgQWN0aW9uOjpFc2MoIlx4MWJPRCIuaW50bygpKTsKCiAgICAgICAgLy8gVkkgTW9kZQogICAgICAgIEtleTo6TmFtZWQoU3BhY2UpLCBNb2RpZmllcnNTdGF0ZTo6QUxUIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlRvZ2dsZVZpTW9kZTsKICAgICAgICAiLyIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNlYXJjaEZvcndhcmQ7CiAgICAgICAgIm4iLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hGb2N1c05leHQ7CiAgICAgICAgIm4iLCAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hGb2N1c1ByZXZpb3VzOwogICAgICAgIEtleTo6TmFtZWQoRW50ZXIpLCArQmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgU2VhcmNoQWN0aW9uOjpTZWFyY2hGb2N1c05leHQ7CiAgICAgICAgS2V5OjpOYW1lZChFbnRlciksICtCaW5kaW5nTW9kZTo6U0VBUkNILCArQmluZGluZ01vZGU6OlZJOyBTZWFyY2hBY3Rpb246OlNlYXJjaENvbmZpcm07CiAgICAgICAgS2V5OjpOYW1lZChFc2NhcGUpLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hDYW5jZWw7CiAgICAgICAgS2V5OjpOYW1lZChFbnRlciksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IFNlYXJjaEFjdGlvbjo6U2VhcmNoRm9jdXNQcmV2aW91czsKICAgICAgICAiaSIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlRvZ2dsZVZpTW9kZTsKICAgICAgICAiYyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlRvZ2dsZVZpTW9kZTsKICAgICAgICBLZXk6Ok5hbWVkKEVzY2FwZSksICtCaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6Q2xlYXJTZWxlY3Rpb247CiAgICAgICAgImkiLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTY3JvbGxUb0JvdHRvbTsKICAgICAgICAiZyIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNjcm9sbFRvVG9wOwogICAgICAgICJnIiwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTY3JvbGxUb0JvdHRvbTsKICAgICAgICAiYiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTY3JvbGxQYWdlVXA7CiAgICAgICAgImYiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6U2Nyb2xsUGFnZURvd247CiAgICAgICAgInUiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6U2Nyb2xsSGFsZlBhZ2VVcDsKICAgICAgICAiZCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTY3JvbGxIYWxmUGFnZURvd247CiAgICAgICAgInkiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNjcm9sbCgxKTsKICAgICAgICAiZSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6U2Nyb2xsKC0xKTsKICAgICAgICAieSIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkNvcHk7CiAgICAgICAgInkiLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpDbGVhclNlbGVjdGlvbjsKICAgICAgICAidiIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaUFjdGlvbjo6VG9nZ2xlTm9ybWFsU2VsZWN0aW9uOwogICAgICAgICJ2IiwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgVmlBY3Rpb246OlRvZ2dsZUxpbmVTZWxlY3Rpb247CiAgICAgICAgInYiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IFZpQWN0aW9uOjpUb2dnbGVCbG9ja1NlbGVjdGlvbjsKICAgICAgICAidiIsIE1vZGlmaWVyc1N0YXRlOjpBTFQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaUFjdGlvbjo6VG9nZ2xlU2VtYW50aWNTZWxlY3Rpb247CiAgICAgICAgInoiLCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgVmlBY3Rpb246OkNlbnRlckFyb3VuZFZpQ3Vyc29yOwogICAgICAgICJrIiwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IFZpTW90aW9uOjpVcDsKICAgICAgICAiaiIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaU1vdGlvbjo6RG93bjsKICAgICAgICAiaCIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaU1vdGlvbjo6TGVmdDsKICAgICAgICAibCIsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBWaU1vdGlvbjo6UmlnaHQ7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd1VwKSwgK0JpbmRpbmdNb2RlOjpWSTsgVmlNb3Rpb246OlVwOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dEb3duKSwgK0JpbmRpbmdNb2RlOjpWSTsgVmlNb3Rpb246OkRvd247CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd0xlZnQpLCArQmluZGluZ01vZGU6OlZJOyBWaU1vdGlvbjo6TGVmdDsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93UmlnaHQpLCArQmluZGluZ01vZGU6OlZJOyBWaU1vdGlvbjo6UmlnaHQ7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd1VwKSwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246Ok5vbmU7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVIsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6Tm9uZTsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93TGVmdCksIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpOb25lOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dSaWdodCksIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpOb25lOwogICAgICAgICIwIiwgICAgICAgICAgICAgICAgICAgICAgICAgICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6Rmlyc3Q7CiAgICAgICAgIjQiLCAgIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpMYXN0OwogICAgICAgICI2IiwgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6Rmlyc3RPY2N1cGllZDsKICAgICAgICAiaCIsICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsKICAgICAgICAgICAgVmlNb3Rpb246OkhpZ2g7CiAgICAgICAgIm0iLCAgICAgIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpNaWRkbGU7CiAgICAgICAgImwiLCAgICAgIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpMb3c7CiAgICAgICAgImIiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpTZW1hbnRpY0xlZnQ7CiAgICAgICAgInciLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgK0JpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIFZpTW90aW9uOjpTZW1hbnRpY1JpZ2h0OwogICAgICAgICJlIiwgICAgICAgICAgICAgICAgICAgICAgICAgICAgICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6U2VtYW50aWNSaWdodEVuZDsKICAgICAgICAiYiIsICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsKICAgICAgICAgICAgVmlNb3Rpb246OldvcmRMZWZ0OwogICAgICAgICJ3IiwgICAgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6V29yZFJpZ2h0OwogICAgICAgICJlIiwgICAgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6V29yZFJpZ2h0RW5kOwogICAgICAgICI1IiwgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBWaU1vdGlvbjo6QnJhY2tldDsKICAgICk7CgogICAgaWYgIWNvbmZpZ19rZXlib2FyZC51c2Vfa2l0dHlfa2V5Ym9hcmRfcHJvdG9jb2wgewogICAgICAgIGJpbmRpbmdzLmV4dGVuZChiaW5kaW5ncyEoCiAgICAgICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgICAgIEtleTo6TmFtZWQoSG9tZSksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkVzYygiXHgxYlsxOzJIIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEVuZCksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgK0JpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkVzYygiXHgxYlsxOzJGIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEVuZCksICB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6RXNjKCJceDFiW0YiLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoUGFnZVVwKSwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYls1OzJ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VEb3duKSwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCArQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYls2OzJ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEhvbWUpLCAgfkJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbSCIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd1VwKSwgfkJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbQSIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYltCIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEFycm93UmlnaHQpLCB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYltDIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEFycm93TGVmdCksICB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYltEIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEJhY2tzcGFjZSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHg3ZiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChJbnNlcnQpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMn4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRGVsZXRlKSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzN+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VVcCksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYls1fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChQYWdlRG93biksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYls2fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYk9QIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEYyKSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiT1EiLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjMpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJPUiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGNCksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYk9TIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEY1KSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzE1fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGNiksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlsxN34iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjcpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMTh+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEY4KSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzE5fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGOSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlsyMH4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjEwKSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzIxfiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMTEpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMjN+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEYxMiksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlsyNH4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjEzKSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzI1fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMTQpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMjZ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEYxNSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlsyOH4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjE2KSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzI5fiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMTcpLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMzF+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEYxOCksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OkVzYygiXHgxYlszMn4iLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoRjE5KSwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7IEFjdGlvbjo6RXNjKCJceDFiWzMzfiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMjApLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpFc2MoIlx4MWJbMzR+Ii5pbnRvKCkpOwogICAgICAgICkpOwoKICAgICAgICAvLyAgIENvZGUgICAgIE1vZGlmaWVycwogICAgICAgIC8vIC0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgICAgICAvLyAgICAyICAgICB8IFNoaWZ0CiAgICAgICAgLy8gICAgMyAgICAgfCBBbHQKICAgICAgICAvLyAgICA0ICAgICB8IFNoaWZ0ICsgQWx0CiAgICAgICAgLy8gICAgNSAgICAgfCBDb250cm9sCiAgICAgICAgLy8gICAgNiAgICAgfCBTaGlmdCArIENvbnRyb2wKICAgICAgICAvLyAgICA3ICAgICB8IEFsdCArIENvbnRyb2wKICAgICAgICAvLyAgICA4ICAgICB8IFNoaWZ0ICsgQWx0ICsgQ29udHJvbAogICAgICAgIC8vIC0tLS0tLS0tLSstLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAgICAgICAvLwogICAgICAgIC8vIGZyb206IGh0dHBzOi8vaW52aXNpYmxlLWlzbGFuZC5uZXQveHRlcm0vY3Rsc2Vxcy9jdGxzZXFzLmh0bWwjaDItUEMtU3R5bGUtRnVuY3Rpb24tS2V5cwogICAgICAgIGxldCBtdXQgbW9kaWZpZXJzID0gdmVjIVsKICAgICAgICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULAogICAgICAgICAgICBNb2RpZmllcnNTdGF0ZTo6QUxULAogICAgICAgICAgICBNb2RpZmllcnNTdGF0ZTo6U0hJRlQgfCBNb2RpZmllcnNTdGF0ZTo6QUxULAogICAgICAgICAgICBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwKICAgICAgICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZUIHwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsCiAgICAgICAgICAgIE1vZGlmaWVyc1N0YXRlOjpBTFQgfCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwKICAgICAgICAgICAgTW9kaWZpZXJzU3RhdGU6OlNISUZUIHwgTW9kaWZpZXJzU3RhdGU6OkFMVCB8IE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLAogICAgICAgIF07CgogICAgICAgIGZvciAoaW5kZXgsIG1vZHMpIGluIG1vZGlmaWVycy5kcmFpbiguLikuZW51bWVyYXRlKCkgewogICAgICAgICAgICAvLyBJZiBkaXNhYmxlX2N0bHNlcXNfYWx0IGlzIGVuYWJsZWQsIHNob3VsZCBpZ25vcmUgQUxUCiAgICAgICAgICAgIC8vIFVzZWZ1bCBmb3IgZXhhbXBsZSBpZiB3YW50IHNhbWUgYmVoYXZpb3VyIHRoYXQgVGVybWluYWwuYXBwIGhhdmUKICAgICAgICAgICAgLy8gU2luY2UgVGVybWluYWwuYXBwIGRvZXMgbm90IGRlYWwgd2l0aCBjdGxzZXFzIHdpdGggQUxUIGtleXMKICAgICAgICAgICAgaWYgaW5kZXggPT0gMSAmJiBjb25maWdfa2V5Ym9hcmQuZGlzYWJsZV9jdGxzZXFzX2FsdCB7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgbGV0IG1vZGlmaWVyc19jb2RlID0gaW5kZXggKyAyOwogICAgICAgICAgICBiaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRGVsZXRlKSwgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzM7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoQXJyb3dVcCksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fUEiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsxO3t9QiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEFycm93UmlnaHQpLCAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzE7e31DIiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoQXJyb3dMZWZ0KSwgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fUQiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMSksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fVAiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMiksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fVEiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMyksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fVIiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGNCksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fVMiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGNSksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTU7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjYpLCAgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzE3O3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEY3KSwgICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsxODt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGOCksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTk7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjkpLCAgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzIwO3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEYxMCksICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsyMTt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMTEpLCAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMjM7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjEyKSwgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzI0O3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEYxMyksICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsyNTt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMTQpLCAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMjY7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjE1KSwgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzI4O3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEYxNiksICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlsyOTt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMTcpLCAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMzE7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoRjE4KSwgICAgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzMyO3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKEYxOSksICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYlszMzt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgS2V5OjpOYW1lZChGMjApLCAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMzQ7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgKSk7CgogICAgICAgICAgICAvLyBXZSdyZSBhZGRpbmcgdGhlIGZvbGxvd2luZyBiaW5kaW5ncyB3aXRoIGBTaGlmdGAgbWFudWFsbHkgYWJvdmUsIHNvIHNraXBwaW5nIHRoZW0gaGVyZS4KICAgICAgICAgICAgaWYgbW9kaWZpZXJzX2NvZGUgIT0gMiB7CiAgICAgICAgICAgICAgICBiaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICAgICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgICAgICAgICAgICAgS2V5OjpOYW1lZChJbnNlcnQpLCAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMjt7fX4iLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoUGFnZVVwKSwgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzU7e31+IiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VEb3duKSwgbW9kcywgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgICAgICAgICAgQWN0aW9uOjpFc2MoZm9ybWF0ISgiXHgxYls2O3t9fiIsIG1vZGlmaWVyc19jb2RlKSk7CiAgICAgICAgICAgICAgICAgICAgS2V5OjpOYW1lZChFbmQpLCAgICAgIG1vZHMsIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKGZvcm1hdCEoIlx4MWJbMTt7fUYiLCBtb2RpZmllcnNfY29kZSkpOwogICAgICAgICAgICAgICAgICAgIEtleTo6TmFtZWQoSG9tZSksICAgICBtb2RzLCB+QmluZGluZ01vZGU6OlZJOwogICAgICAgICAgICAgICAgICAgICAgICBBY3Rpb246OkVzYyhmb3JtYXQhKCJceDFiWzE7e31IIiwgbW9kaWZpZXJzX2NvZGUpKTsKICAgICAgICAgICAgICAgICkpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgICBiaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEFycm93VXApLCB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQzsgQWN0aW9uOjpFc2MoIlx4MWJbQSIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCB+QmluZGluZ01vZGU6OkFQUF9DVVJTT1IsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQzsgQWN0aW9uOjpFc2MoIlx4MWJbQiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd1JpZ2h0KSwgfkJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLCB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0M7IEFjdGlvbjo6RXNjKCJceDFiW0MiLmludG8oKSk7CiAgICAgICAgICAgIEtleTo6TmFtZWQoQXJyb3dMZWZ0KSwgIH5CaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6QUxMX0tFWVNfQVNfRVNDOyBBY3Rpb246OkVzYygiXHgxYltEIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEluc2VydCksICAgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0MsIH5CaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVM7IEFjdGlvbjo6RXNjKCJceDFiWzJ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKERlbGV0ZSksICAgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0MsIH5CaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVM7IEFjdGlvbjo6RXNjKCJceDFiWzN+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VVcCksICAgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0MsIH5CaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVM7IEFjdGlvbjo6RXNjKCJceDFiWzV+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFBhZ2VEb3duKSwgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0MsIH5CaW5kaW5nTW9kZTo6RElTQU1CSUdVQVRFX0tFWVM7IEFjdGlvbjo6RXNjKCJceDFiWzZ+Ii5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEJhY2tzcGFjZSksICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0M7IEFjdGlvbjo6RXNjKCJceDdmIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKEJhY2tzcGFjZSksIE1vZGlmaWVyc1N0YXRlOjpBTFQsICAgICB+QmluZGluZ01vZGU6OlZJLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpBTExfS0VZU19BU19FU0M7IEFjdGlvbjo6RXNjKCJceDFiXHg3ZiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChCYWNrc3BhY2UpLCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICAgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6QUxMX0tFWVNfQVNfRVNDOyBBY3Rpb246OkVzYygiXHg3ZiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMSksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQywgfkJpbmRpbmdNb2RlOjpESVNBTUJJR1VBVEVfS0VZUzsgQWN0aW9uOjpFc2MoIlx4MWJPUCIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMiksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQywgfkJpbmRpbmdNb2RlOjpESVNBTUJJR1VBVEVfS0VZUzsgQWN0aW9uOjpFc2MoIlx4MWJPUSIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGMyksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQywgfkJpbmRpbmdNb2RlOjpESVNBTUJJR1VBVEVfS0VZUzsgQWN0aW9uOjpFc2MoIlx4MWJPUiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChGNCksIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQywgfkJpbmRpbmdNb2RlOjpESVNBTUJJR1VBVEVfS0VZUzsgQWN0aW9uOjpFc2MoIlx4MWJPUyIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChUYWIpLCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCAgIH5CaW5kaW5nTW9kZTo6QUxMX0tFWVNfQVNfRVNDOyBBY3Rpb246OkVzYygiXHgxYltaIi5pbnRvKCkpOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFRhYiksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCB8IE1vZGlmaWVyc1N0YXRlOjpBTFQsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OkFMTF9LRVlTX0FTX0VTQzsgQWN0aW9uOjpFc2MoIlx4MWJceDFiW1oiLmludG8oKSk7CiAgICAgICAgKSk7CiAgICB9CgogICAgYmluZGluZ3MuZXh0ZW5kKHBsYXRmb3JtX2tleV9iaW5kaW5ncygKICAgICAgICB1c2VfbmF2aWdhdGlvbl9rZXlfYmluZGluZ3MsCiAgICAgICAgdXNlX3NwbGl0cywKICAgICAgICBjb25maWdfa2V5Ym9hcmQsCiAgICApKTsKCiAgICBjb25maWdfa2V5X2JpbmRpbmdzKHVucHJvY2Vzc2VkX2NvbmZpZ19rZXlfYmluZGluZ3MsIGJpbmRpbmdzKQp9CgojW2Rlcml2ZShDbG9uZSwgRGVidWcsIFBhcnRpYWxFcSwgRXEpXQpwdWIgc3RydWN0IE1vZGVXcmFwcGVyIHsKICAgIHB1YiBtb2RlOiBCaW5kaW5nTW9kZSwKICAgIHB1YiBub3RfbW9kZTogQmluZGluZ01vZGUsCn0KCiNbaW5saW5lXQpmbiBjb252ZXJ0KGNvbmZpZ19rZXlfYmluZGluZzogQ29uZmlnS2V5QmluZGluZykgLT4gUmVzdWx0PEtleUJpbmRpbmcsIFN0cmluZz4gewogICAgbGV0IChrZXksIGxvY2F0aW9uKSA9IGlmIGNvbmZpZ19rZXlfYmluZGluZy5rZXkuY2hhcnMoKS5jb3VudCgpID09IDEgewogICAgICAgICgKICAgICAgICAgICAgS2V5OjpDaGFyYWN0ZXIoY29uZmlnX2tleV9iaW5kaW5nLmtleS50b19sb3dlcmNhc2UoKS5pbnRvKCkpLAogICAgICAgICAgICBLZXlMb2NhdGlvbjo6U3RhbmRhcmQsCiAgICAgICAgKQogICAgfSBlbHNlIHsKICAgICAgICBtYXRjaCBjb25maWdfa2V5X2JpbmRpbmcua2V5LnRvX2xvd2VyY2FzZSgpLmFzX3N0cigpIHsKICAgICAgICAgICAgImhvbWUiID0+IChLZXk6Ok5hbWVkKEhvbWUpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICAic3BhY2UiID0+IChLZXk6Ok5hbWVkKFNwYWNlKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgImRlbGV0ZSIgPT4gKEtleTo6TmFtZWQoRGVsZXRlKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgImVzYyIgPT4gKEtleTo6TmFtZWQoRXNjYXBlKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgImluc2VydCIgPT4gKEtleTo6TmFtZWQoSW5zZXJ0KSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgInBhZ2V1cCIgPT4gKEtleTo6TmFtZWQoUGFnZVVwKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgInBhZ2Vkb3duIiA9PiAoS2V5OjpOYW1lZChQYWdlRG93biksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJlbmQiID0+IChLZXk6Ok5hbWVkKEVuZCksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJ1cCIgPT4gKEtleTo6TmFtZWQoQXJyb3dVcCksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJiYWNrIiA9PiAoS2V5OjpOYW1lZChCYWNrc3BhY2UpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICAiZG93biIgPT4gKEtleTo6TmFtZWQoQXJyb3dEb3duKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgImxlZnQiID0+IChLZXk6Ok5hbWVkKEFycm93TGVmdCksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJyaWdodCIgPT4gKEtleTo6TmFtZWQoQXJyb3dSaWdodCksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJAIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIkAiLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJjb2xvbiIgPT4gKEtleTo6Q2hhcmFjdGVyKCI6Ii5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICAiLiIgPT4gKEtleTo6Q2hhcmFjdGVyKCIuIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICAicmV0dXJuIiA9PiAoS2V5OjpOYW1lZChFbnRlciksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJbIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIlsiLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJdIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIl0iLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJ7IiA9PiAoS2V5OjpDaGFyYWN0ZXIoInsiLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJ9IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIn0iLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICI7IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjsiLmludG8oKSksIEtleUxvY2F0aW9uOjpTdGFuZGFyZCksCiAgICAgICAgICAgICJcXCIgPT4gKEtleTo6Q2hhcmFjdGVyKCJcXCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIisiID0+IChLZXk6OkNoYXJhY3RlcigiKyIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIiwiID0+IChLZXk6OkNoYXJhY3RlcigiLCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIi8iID0+IChLZXk6OkNoYXJhY3RlcigiLyIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIj0iID0+IChLZXk6OkNoYXJhY3RlcigiPSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIi0iID0+IChLZXk6OkNoYXJhY3RlcigiLSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIioiID0+IChLZXk6OkNoYXJhY3RlcigiKiIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjEiID0+IChLZXk6OkNoYXJhY3RlcigiMSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjIiID0+IChLZXk6OkNoYXJhY3RlcigiMiIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjMiID0+IChLZXk6OkNoYXJhY3RlcigiMyIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjQiID0+IChLZXk6OkNoYXJhY3RlcigiNCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjUiID0+IChLZXk6OkNoYXJhY3RlcigiNSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjYiID0+IChLZXk6OkNoYXJhY3RlcigiNiIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjciID0+IChLZXk6OkNoYXJhY3RlcigiNyIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjgiID0+IChLZXk6OkNoYXJhY3RlcigiOCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjkiID0+IChLZXk6OkNoYXJhY3RlcigiOSIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKICAgICAgICAgICAgIjAiID0+IChLZXk6OkNoYXJhY3RlcigiMCIuaW50bygpKSwgS2V5TG9jYXRpb246OlN0YW5kYXJkKSwKCiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBudW1wYWQuCiAgICAgICAgICAgICJudW1wYWRlbnRlciIgPT4gKEtleTo6TmFtZWQoRW50ZXIpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZGFkZCIgPT4gKEtleTo6Q2hhcmFjdGVyKCIrIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZGNvbW1hIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIiwiLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkZGVjaW1hbCIgPT4gKEtleTo6Q2hhcmFjdGVyKCIuIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZGRpdmlkZSIgPT4gKEtleTo6Q2hhcmFjdGVyKCIvIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZGVxdWFscyIgPT4gKEtleTo6Q2hhcmFjdGVyKCI9Ii5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZHN1YnRyYWN0IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIi0iLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkbXVsdGlwbHkiID0+IChLZXk6OkNoYXJhY3RlcigiKiIuaW50bygpKSwgS2V5TG9jYXRpb246Ok51bXBhZCksCiAgICAgICAgICAgICJudW1wYWQxIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjEiLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkMiIgPT4gKEtleTo6Q2hhcmFjdGVyKCIyIi5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZDMiID0+IChLZXk6OkNoYXJhY3RlcigiMyIuaW50bygpKSwgS2V5TG9jYXRpb246Ok51bXBhZCksCiAgICAgICAgICAgICJudW1wYWQ0IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjQiLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkNSIgPT4gKEtleTo6Q2hhcmFjdGVyKCI1Ii5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZDYiID0+IChLZXk6OkNoYXJhY3RlcigiNiIuaW50bygpKSwgS2V5TG9jYXRpb246Ok51bXBhZCksCiAgICAgICAgICAgICJudW1wYWQ3IiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjciLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAogICAgICAgICAgICAibnVtcGFkOCIgPT4gKEtleTo6Q2hhcmFjdGVyKCI4Ii5pbnRvKCkpLCBLZXlMb2NhdGlvbjo6TnVtcGFkKSwKICAgICAgICAgICAgIm51bXBhZDkiID0+IChLZXk6OkNoYXJhY3RlcigiOSIuaW50bygpKSwgS2V5TG9jYXRpb246Ok51bXBhZCksCiAgICAgICAgICAgICJudW1wYWQwIiA9PiAoS2V5OjpDaGFyYWN0ZXIoIjAiLmludG8oKSksIEtleUxvY2F0aW9uOjpOdW1wYWQpLAoKICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlcwogICAgICAgICAgICAidGFiIiA9PiAoS2V5OjpOYW1lZChUYWIpLCBLZXlMb2NhdGlvbjo6U3RhbmRhcmQpLAogICAgICAgICAgICBfID0+IHJldHVybiBFcnIoIlVuYWJsZSB0byBmaW5kIGRlZmluZWQgJ2tleWNvZGUnIi50b19zdHJpbmcoKSksCiAgICAgICAgfQogICAgfTsKCiAgICBsZXQgdHJpZ2dlciA9IEJpbmRpbmdLZXk6OktleWNvZGUgeyBrZXksIGxvY2F0aW9uIH07CgogICAgbGV0IG11dCByZXMgPSBNb2RpZmllcnNTdGF0ZTo6ZW1wdHkoKTsKICAgIGZvciBtb2RpZmllciBpbiBjb25maWdfa2V5X2JpbmRpbmcud2l0aC5zcGxpdCgnfCcpIHsKICAgICAgICBtYXRjaCBtb2RpZmllci50cmltKCkudG9fbG93ZXJjYXNlKCkuYXNfc3RyKCkgewogICAgICAgICAgICAiY29tbWFuZCIgfCAic3VwZXIiID0+IHJlcy5pbnNlcnQoTW9kaWZpZXJzU3RhdGU6OlNVUEVSKSwKICAgICAgICAgICAgInNoaWZ0IiA9PiByZXMuaW5zZXJ0KE1vZGlmaWVyc1N0YXRlOjpTSElGVCksCiAgICAgICAgICAgICJhbHQiIHwgIm9wdGlvbiIgPT4gcmVzLmluc2VydChNb2RpZmllcnNTdGF0ZTo6QUxUKSwKICAgICAgICAgICAgImNvbnRyb2wiID0+IHJlcy5pbnNlcnQoTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wpLAogICAgICAgICAgICAibm9uZSIgPT4gKCksCiAgICAgICAgICAgIF8gPT4gKCksCiAgICAgICAgfQogICAgfQoKICAgIGxldCBtdXQgYWN0aW9uOiBBY3Rpb24gPSBjb25maWdfa2V5X2JpbmRpbmcuYWN0aW9uLmludG8oKTsKICAgIGlmICFjb25maWdfa2V5X2JpbmRpbmcudGV4dC5pc19lbXB0eSgpIHsKICAgICAgICBhY3Rpb24gPSBBY3Rpb246OkVzYyhjb25maWdfa2V5X2JpbmRpbmcudGV4dCk7CiAgICB9CgogICAgaWYgIWNvbmZpZ19rZXlfYmluZGluZy5ieXRlcy5pc19lbXB0eSgpIHsKICAgICAgICBpZiBsZXQgT2soc3RyX2Zyb21fYnl0ZXMpID0gc3RkOjpzdHI6OmZyb21fdXRmOCgmY29uZmlnX2tleV9iaW5kaW5nLmJ5dGVzKSB7CiAgICAgICAgICAgIGFjdGlvbiA9IEFjdGlvbjo6RXNjKHN0cl9mcm9tX2J5dGVzLmludG8oKSk7CiAgICAgICAgfQogICAgfQoKICAgIGxldCBtdXQgcmVzX21vZGUgPSBNb2RlV3JhcHBlciB7CiAgICAgICAgbW9kZTogQmluZGluZ01vZGU6OmVtcHR5KCksCiAgICAgICAgbm90X21vZGU6IEJpbmRpbmdNb2RlOjplbXB0eSgpLAogICAgfTsKCiAgICBmb3IgbW9kaWZpZXIgaW4gY29uZmlnX2tleV9iaW5kaW5nLm1vZGUuc3BsaXQoJ3wnKSB7CiAgICAgICAgbWF0Y2ggbW9kaWZpZXIudHJpbSgpLnRvX2xvd2VyY2FzZSgpLmFzX3N0cigpIHsKICAgICAgICAgICAgImFwcGN1cnNvciIgPT4gcmVzX21vZGUubW9kZSB8PSBCaW5kaW5nTW9kZTo6QVBQX0NVUlNPUiwKICAgICAgICAgICAgIn5hcHBjdXJzb3IiID0+IHJlc19tb2RlLm5vdF9tb2RlIHw9IEJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLAogICAgICAgICAgICAiYXBwa2V5cGFkIiA9PiByZXNfbW9kZS5tb2RlIHw9IEJpbmRpbmdNb2RlOjpBUFBfS0VZUEFELAogICAgICAgICAgICAifmFwcGtleXBhZCIgPT4gcmVzX21vZGUubm90X21vZGUgfD0gQmluZGluZ01vZGU6OkFQUF9LRVlQQUQsCiAgICAgICAgICAgICJhbHQiID0+IHJlc19tb2RlLm1vZGUgfD0gQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sCiAgICAgICAgICAgICJ+YWx0IiA9PiByZXNfbW9kZS5ub3RfbW9kZSB8PSBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgInZpIiA9PiByZXNfbW9kZS5tb2RlIHw9IEJpbmRpbmdNb2RlOjpWSSwKICAgICAgICAgICAgIn52aSIgPT4gcmVzX21vZGUubm90X21vZGUgfD0gQmluZGluZ01vZGU6OlZJLAogICAgICAgICAgICBfID0+IHsKICAgICAgICAgICAgICAgIHJlc19tb2RlLm5vdF9tb2RlIHw9IEJpbmRpbmdNb2RlOjplbXB0eSgpOwogICAgICAgICAgICAgICAgcmVzX21vZGUubW9kZSB8PSBCaW5kaW5nTW9kZTo6ZW1wdHkoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBPayhLZXlCaW5kaW5nIHsKICAgICAgICB0cmlnZ2VyLAogICAgICAgIG1vZHM6IHJlcywKICAgICAgICBhY3Rpb24sCiAgICAgICAgbW9kZTogcmVzX21vZGUubW9kZSwKICAgICAgICBub3Rtb2RlOiByZXNfbW9kZS5ub3RfbW9kZSwKICAgIH0pCn0KCnB1YiBmbiBjb25maWdfa2V5X2JpbmRpbmdzKAogICAgY29uZmlnX2tleV9iaW5kaW5nczogVmVjPENvbmZpZ0tleUJpbmRpbmc+LAogICAgbXV0IGJpbmRpbmdzOiBWZWM8S2V5QmluZGluZz4sCikgLT4gVmVjPEtleUJpbmRpbmc+IHsKICAgIGlmIGNvbmZpZ19rZXlfYmluZGluZ3MuaXNfZW1wdHkoKSB7CiAgICAgICAgcmV0dXJuIGJpbmRpbmdzOwogICAgfQoKICAgIGZvciBja2IgaW4gY29uZmlnX2tleV9iaW5kaW5ncyB7CiAgICAgICAgbWF0Y2ggY29udmVydChja2IpIHsKICAgICAgICAgICAgT2soa2V5X2JpbmRpbmcpID0+IG1hdGNoIGtleV9iaW5kaW5nLmFjdGlvbiB7CiAgICAgICAgICAgICAgICBBY3Rpb246Ok5vbmUgfCBBY3Rpb246OlJlY2VpdmVDaGFyID0+IHsKICAgICAgICAgICAgICAgICAgICBsZXQgbXV0IGZvdW5kX2lkeCA9IE5vbmU7CiAgICAgICAgICAgICAgICAgICAgZm9yIChpZHgsIGJpbmRpbmcpIGluIGJpbmRpbmdzLml0ZXIoKS5lbnVtZXJhdGUoKSB7CiAgICAgICAgICAgICAgICAgICAgICAgIGlmIGJpbmRpbmcudHJpZ2dlcnNfbWF0Y2goJmtleV9iaW5kaW5nKSB7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3VuZF9pZHggPSBTb21lKGlkeCk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgaWYgbGV0IFNvbWUoaWR4KSA9IGZvdW5kX2lkeCB7CiAgICAgICAgICAgICAgICAgICAgICAgIGJpbmRpbmdzLnJlbW92ZShpZHgpOwogICAgICAgICAgICAgICAgICAgICAgICB0cmFjaW5nOjp3YXJuISgKICAgICAgICAgICAgICAgICAgICAgICAgICAgICJvdmVyd3JpdHRlbiBhIHByZXZpb3VzIGtleV9iaW5kaW5nIHdpdGggbmV3IG9uZTogezo/fSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlfYmluZGluZwogICAgICAgICAgICAgICAgICAgICAgICApOwogICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNpbmc6OmluZm8hKCJhZGRlZCBhIG5ldyBrZXlfYmluZGluZzogezo/fSIsIGtleV9iaW5kaW5nKTsKICAgICAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgICAgIGJpbmRpbmdzLnB1c2goa2V5X2JpbmRpbmcpCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBfID0+IHsKICAgICAgICAgICAgICAgICAgICB0cmFjaW5nOjppbmZvISgiYWRkZWQgYSBuZXcga2V5X2JpbmRpbmc6IHs6P30iLCBrZXlfYmluZGluZyk7CiAgICAgICAgICAgICAgICAgICAgYmluZGluZ3MucHVzaChrZXlfYmluZGluZykKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwKICAgICAgICAgICAgRXJyKGVycl9tZXNzYWdlKSA9PiB7CiAgICAgICAgICAgICAgICB0cmFjaW5nOjplcnJvciEoImVycm9yIGxvYWRpbmcgYSBrZXkgYmluZGluZzogezo/fSIsIGVycl9tZXNzYWdlKTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBiaW5kaW5ncwp9CgovLyBNYWNvcwojW2NmZyhhbGwodGFyZ2V0X29zID0gIm1hY29zIiwgbm90KHRlc3QpKSldCnB1YiBmbiBwbGF0Zm9ybV9rZXlfYmluZGluZ3MoCiAgICB1c2VfbmF2aWdhdGlvbl9rZXlfYmluZGluZ3M6IGJvb2wsCiAgICB1c2Vfc3BsaXRzOiBib29sLAogICAgY29uZmlnX2tleWJvYXJkOiBDb25maWdLZXlib2FyZCwKKSAtPiBWZWM8S2V5QmluZGluZz4gewogICAgbGV0IG11dCBrZXlfYmluZGluZ3MgPSBiaW5kaW5ncyEoCiAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAiMCIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpSZXNldEZvbnRTaXplOwogICAgICAgICI9IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OkluY3JlYXNlRm9udFNpemU7CiAgICAgICAgIisiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6SW5jcmVhc2VGb250U2l6ZTsKICAgICAgICAiKyIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpJbmNyZWFzZUZvbnRTaXplOwogICAgICAgICItIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OkRlY3JlYXNlRm9udFNpemU7CiAgICAgICAgIi0iLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6RGVjcmVhc2VGb250U2l6ZTsKICAgICAgICBLZXk6Ok5hbWVkKEluc2VydCksIE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpWSSwgfkJpbmRpbmdNb2RlOjpTRUFSQ0g7CiAgICAgICAgICAgIEFjdGlvbjo6RXNjKCJceDFiWzI7Mn4iLmludG8oKSk7CiAgICAgICAgImsiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVIsIH5CaW5kaW5nTW9kZTo6VkksIH5CaW5kaW5nTW9kZTo6U0VBUkNIOwogICAgICAgICAgICBBY3Rpb246OkVzYygiXHgwYyIuaW50bygpKTsKICAgICAgICAiayIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpWSTsgIEFjdGlvbjo6Q2xlYXJIaXN0b3J5OwogICAgICAgICJ2IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlBhc3RlOwogICAgICAgICJmIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6VG9nZ2xlRnVsbHNjcmVlbjsKICAgICAgICAiYyIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpDb3B5OwogICAgICAgICJjIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCArQmluZGluZ01vZGU6OlZJOyBBY3Rpb246OkNsZWFyU2VsZWN0aW9uOwogICAgICAgICJoIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OkhpZGU7CiAgICAgICAgImgiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVIgfCBNb2RpZmllcnNTdGF0ZTo6QUxUOyBBY3Rpb246OkhpZGVPdGhlckFwcGxpY2F0aW9uczsKICAgICAgICAibSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpNaW5pbWl6ZTsKICAgICAgICAicSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpRdWl0OwogICAgICAgICJuIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OldpbmRvd0NyZWF0ZU5ldzsKICAgICAgICAiLCIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpDb25maWdFZGl0b3I7CgogICAgICAgIC8vIFNlYXJjaAogICAgICAgICJmIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTZWFyY2hGb3J3YXJkOwogICAgICAgICJiIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTZWFyY2hCYWNrd2FyZDsKICAgICAgICAiYyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hDYW5jZWw7CiAgICAgICAgInUiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoQ2xlYXI7CiAgICAgICAgInciLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgICtCaW5kaW5nTW9kZTo6U0VBUkNIOyBTZWFyY2hBY3Rpb246OlNlYXJjaERlbGV0ZVdvcmQ7CiAgICAgICAgInAiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCwgICtCaW5kaW5nTW9kZTo6U0VBUkNIOyBTZWFyY2hBY3Rpb246OlNlYXJjaEhpc3RvcnlQcmV2aW91czsKICAgICAgICAibiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeU5leHQ7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd1VwKSwgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeVByZXZpb3VzOwogICAgICAgIEtleTo6TmFtZWQoQXJyb3dEb3duKSwgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeU5leHQ7CiAgICApOwoKICAgIGlmIHVzZV9uYXZpZ2F0aW9uX2tleV9iaW5kaW5ncyB7CiAgICAgICAga2V5X2JpbmRpbmdzLmV4dGVuZChiaW5kaW5ncyEoCiAgICAgICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgICAgICJ0IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OlRhYkNyZWF0ZU5ldzsKICAgICAgICAgICAgS2V5OjpOYW1lZChUYWIpLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgQWN0aW9uOjpTZWxlY3ROZXh0VGFiOwogICAgICAgICAgICBLZXk6Ok5hbWVkKFRhYiksIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlNlbGVjdFByZXZUYWI7CiAgICAgICAgICAgICJ3IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OkNsb3NlQ3VycmVudFNwbGl0T3JUYWI7CiAgICAgICAgICAgICJbIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlNlbGVjdFByZXZUYWI7CiAgICAgICAgICAgICJdIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlNlbGVjdE5leHRUYWI7CiAgICAgICAgICAgICIxIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OlNlbGVjdFRhYigwKTsKICAgICAgICAgICAgIjIiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6U2VsZWN0VGFiKDEpOwogICAgICAgICAgICAiMyIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpTZWxlY3RUYWIoMik7CiAgICAgICAgICAgICI0IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OlNlbGVjdFRhYigzKTsKICAgICAgICAgICAgIjUiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6U2VsZWN0VGFiKDQpOwogICAgICAgICAgICAiNiIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpTZWxlY3RUYWIoNSk7CiAgICAgICAgICAgICI3IiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSOyBBY3Rpb246OlNlbGVjdFRhYig2KTsKICAgICAgICAgICAgIjgiLCBNb2RpZmllcnNTdGF0ZTo6U1VQRVI7IEFjdGlvbjo6U2VsZWN0VGFiKDcpOwogICAgICAgICAgICAiOSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpTZWxlY3RMYXN0VGFiOwogICAgICAgICkpOwogICAgfQoKICAgIGlmIGNvbmZpZ19rZXlib2FyZC5kaXNhYmxlX2N0bHNlcXNfYWx0IHsKICAgICAgICBrZXlfYmluZGluZ3MuZXh0ZW5kKGJpbmRpbmdzISgKICAgICAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd0xlZnQpLCBNb2RpZmllcnNTdGF0ZTo6QUxULCAgfkJpbmRpbmdNb2RlOjpWSTsKICAgICAgICAgICAgICAgIEFjdGlvbjo6RXNjKCJceDFiYiIuaW50bygpKTsKICAgICAgICAgICAgS2V5OjpOYW1lZChBcnJvd1JpZ2h0KSwgTW9kaWZpZXJzU3RhdGU6OkFMVCwgIH5CaW5kaW5nTW9kZTo6Vkk7CiAgICAgICAgICAgICAgICBBY3Rpb246OkVzYygiXHgxYmYiLmludG8oKSk7CiAgICAgICAgKSk7CiAgICB9CgogICAgaWYgdXNlX3NwbGl0cyB7CiAgICAgICAga2V5X2JpbmRpbmdzLmV4dGVuZChiaW5kaW5ncyEoCiAgICAgICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgICAgICJkIiwgTW9kaWZpZXJzU3RhdGU6OlNVUEVSLCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdFJpZ2h0OwogICAgICAgICAgICAiZCIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U3BsaXREb3duOwogICAgICAgICAgICAiXSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U2VsZWN0TmV4dFNwbGl0OwogICAgICAgICAgICAiWyIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUiwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U2VsZWN0UHJldlNwbGl0OwogICAgICAgICkpOwogICAgfQoKICAgIGtleV9iaW5kaW5ncwp9CgovLyBOb3QgV2luZG93cywgTWFjb3MKI1tjZmcobm90KGFueSh0YXJnZXRfb3MgPSAibWFjb3MiLCB0YXJnZXRfb3MgPSAid2luZG93cyIsIHRlc3QpKSldCnB1YiBmbiBwbGF0Zm9ybV9rZXlfYmluZGluZ3MoCiAgICB1c2VfbmF2aWdhdGlvbl9rZXlfYmluZGluZ3M6IGJvb2wsCiAgICB1c2Vfc3BsaXRzOiBib29sLAogICAgXzogQ29uZmlnS2V5Ym9hcmQsCikgLT4gVmVjPEtleUJpbmRpbmc+IHsKICAgIGxldCBtdXQga2V5X2JpbmRpbmdzID0gYmluZGluZ3MhKAogICAgICAgIEtleUJpbmRpbmc7CiAgICAgICAgInYiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpQYXN0ZTsKICAgICAgICAiYyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OkNvcHk7CiAgICAgICAgImMiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwKICAgICAgICAgICAgK0JpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpDbGVhclNlbGVjdGlvbjsKICAgICAgICBLZXk6Ok5hbWVkKEluc2VydCksICAgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlBhc3RlU2VsZWN0aW9uOwogICAgICAgICIwIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7ICBBY3Rpb246OlJlc2V0Rm9udFNpemU7CiAgICAgICAgIj0iLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgIEFjdGlvbjo6SW5jcmVhc2VGb250U2l6ZTsKICAgICAgICAiKyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyAgQWN0aW9uOjpJbmNyZWFzZUZvbnRTaXplOwogICAgICAgICIrIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7ICBBY3Rpb246OkluY3JlYXNlRm9udFNpemU7CiAgICAgICAgIi0iLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgIEFjdGlvbjo6RGVjcmVhc2VGb250U2l6ZTsKICAgICAgICAiLSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyAgQWN0aW9uOjpEZWNyZWFzZUZvbnRTaXplOwogICAgICAgICJuIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6V2luZG93Q3JlYXRlTmV3OwogICAgICAgICIsIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6Q29uZmlnRWRpdG9yOwoKICAgICAgICAvLyBTZWFyY2gKICAgICAgICAiZiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTZWFyY2hGb3J3YXJkOwogICAgICAgICJiIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNlYXJjaEJhY2t3YXJkOwogICAgICAgICJjIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsICtCaW5kaW5nTW9kZTo6U0VBUkNIOyBTZWFyY2hBY3Rpb246OlNlYXJjaENhbmNlbDsKICAgICAgICAidSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hDbGVhcjsKICAgICAgICAidyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoRGVsZXRlV29yZDsKICAgICAgICAicCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeVByZXZpb3VzOwogICAgICAgICJuIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsICArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dDsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93VXApLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5UHJldmlvdXM7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dDsKICAgICk7CgogICAgaWYgdXNlX25hdmlnYXRpb25fa2V5X2JpbmRpbmdzIHsKICAgICAgICBrZXlfYmluZGluZ3MuZXh0ZW5kKGJpbmRpbmdzISgKICAgICAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAgICAgInQiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpUYWJDcmVhdGVOZXc7CiAgICAgICAgICAgIEtleTo6TmFtZWQoVGFiKSwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7IEFjdGlvbjo6U2VsZWN0TmV4dFRhYjsKICAgICAgICAgICAgS2V5OjpOYW1lZChUYWIpLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpTZWxlY3RQcmV2VGFiOwogICAgICAgICAgICAiWyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OlNlbGVjdFByZXZUYWI7CiAgICAgICAgICAgICJdIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6U2VsZWN0TmV4dFRhYjsKICAgICAgICAgICAgInciLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpDbG9zZUN1cnJlbnRTcGxpdE9yVGFiOwogICAgICAgICkpOwogICAgfQoKICAgIGlmIHVzZV9zcGxpdHMgewogICAgICAgIGtleV9iaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICAgICAiciIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdFJpZ2h0OwogICAgICAgICAgICAiZCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdERvd247CiAgICAgICAgICAgICJdIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlNlbGVjdE5leHRTcGxpdDsKICAgICAgICAgICAgIlsiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U2VsZWN0UHJldlNwbGl0OwogICAgICAgICkpOwogICAgfQoKICAgIGtleV9iaW5kaW5ncwp9CgovLyBXaW5kb3dzCiNbY2ZnKGFsbCh0YXJnZXRfb3MgPSAid2luZG93cyIsIG5vdCh0ZXN0KSkpXQpwdWIgZm4gcGxhdGZvcm1fa2V5X2JpbmRpbmdzKAogICAgdXNlX25hdmlnYXRpb25fa2V5X2JpbmRpbmdzOiBib29sLAogICAgdXNlX3NwbGl0czogYm9vbCwKICAgIF86IENvbmZpZ0tleWJvYXJkLAopIC0+IFZlYzxLZXlCaW5kaW5nPiB7CiAgICBsZXQgbXV0IGtleV9iaW5kaW5ncyA9IGJpbmRpbmdzISgKICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICJ2IiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6UGFzdGU7CiAgICAgICAgImMiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpDb3B5OwogICAgICAgICJjIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsICtCaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6Q2xlYXJTZWxlY3Rpb247CiAgICAgICAgS2V5OjpOYW1lZChJbnNlcnQpLCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6UGFzdGVTZWxlY3Rpb247CiAgICAgICAgIjAiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgQWN0aW9uOjpSZXNldEZvbnRTaXplOwogICAgICAgICI9IiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7IEFjdGlvbjo6SW5jcmVhc2VGb250U2l6ZTsKICAgICAgICAiKyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyBBY3Rpb246OkluY3JlYXNlRm9udFNpemU7CiAgICAgICAgIisiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTDsgQWN0aW9uOjpJbmNyZWFzZUZvbnRTaXplOwogICAgICAgICItIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7IEFjdGlvbjo6RGVjcmVhc2VGb250U2l6ZTsKICAgICAgICAiLSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MOyBBY3Rpb246OkRlY3JlYXNlRm9udFNpemU7CiAgICAgICAgS2V5OjpOYW1lZChFbnRlciksIE1vZGlmaWVyc1N0YXRlOjpBTFQ7IEFjdGlvbjo6VG9nZ2xlRnVsbHNjcmVlbjsKICAgICAgICAibiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OldpbmRvd0NyZWF0ZU5ldzsKICAgICAgICAiLCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OkNvbmZpZ0VkaXRvcjsKICAgICAgICAvLyBUaGlzIGlzIGFjdHVhbGx5IGEgV2luZG93cyBQb3dlcnNoZWxsIHNob3J0Y3V0CiAgICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2FsYWNyaXR0eS9hbGFjcml0dHkvaXNzdWVzLzI5MzAKICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vcmFwaGFtb3JpbS9yaW8vaXNzdWVzLzIyMCNpc3N1ZWNvbW1lbnQtMTc2MTY1MTMzOQogICAgICAgIEtleTo6TmFtZWQoQmFja3NwYWNlKSwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6RXNjKCJcdXswMDE3fSIuaW50bygpKTsKICAgICAgICBLZXk6Ok5hbWVkKFNwYWNlKSwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6VG9nZ2xlVmlNb2RlOwoKICAgICAgICAvLyBTZWFyY2gKICAgICAgICAiZiIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSDsgQWN0aW9uOjpTZWFyY2hGb3J3YXJkOwogICAgICAgICJiIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6U0VBUkNIOyBBY3Rpb246OlNlYXJjaEJhY2t3YXJkOwogICAgICAgICJjIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsICtCaW5kaW5nTW9kZTo6U0VBUkNIOyBTZWFyY2hBY3Rpb246OlNlYXJjaENhbmNlbDsKICAgICAgICAidSIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hDbGVhcjsKICAgICAgICAidyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoRGVsZXRlV29yZDsKICAgICAgICAicCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MLCAgK0JpbmRpbmdNb2RlOjpTRUFSQ0g7IFNlYXJjaEFjdGlvbjo6U2VhcmNoSGlzdG9yeVByZXZpb3VzOwogICAgICAgICJuIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wsICArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dDsKICAgICAgICBLZXk6Ok5hbWVkKEFycm93VXApLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5UHJldmlvdXM7CiAgICAgICAgS2V5OjpOYW1lZChBcnJvd0Rvd24pLCArQmluZGluZ01vZGU6OlNFQVJDSDsgU2VhcmNoQWN0aW9uOjpTZWFyY2hIaXN0b3J5TmV4dDsKICAgICk7CgogICAgaWYgdXNlX25hdmlnYXRpb25fa2V5X2JpbmRpbmdzIHsKICAgICAgICBrZXlfYmluZGluZ3MuZXh0ZW5kKGJpbmRpbmdzISgKICAgICAgICAgICAgS2V5QmluZGluZzsKICAgICAgICAgICAgInQiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpUYWJDcmVhdGVOZXc7CiAgICAgICAgICAgIEtleTo6TmFtZWQoVGFiKSwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0w7IEFjdGlvbjo6U2VsZWN0TmV4dFRhYjsKICAgICAgICAgICAgS2V5OjpOYW1lZChUYWIpLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpTZWxlY3RQcmV2VGFiOwogICAgICAgICAgICAidyIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZUOyBBY3Rpb246OkNsb3NlQ3VycmVudFNwbGl0T3JUYWI7CiAgICAgICAgICAgICJbIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQ7IEFjdGlvbjo6U2VsZWN0UHJldlRhYjsKICAgICAgICAgICAgIl0iLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVDsgQWN0aW9uOjpTZWxlY3ROZXh0VGFiOwogICAgICAgICkpOwogICAgfQoKICAgIGlmIHVzZV9zcGxpdHMgewogICAgICAgIGtleV9iaW5kaW5ncy5leHRlbmQoYmluZGluZ3MhKAogICAgICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICAgICAiciIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdFJpZ2h0OwogICAgICAgICAgICAiZCIsIE1vZGlmaWVyc1N0YXRlOjpDT05UUk9MIHwgTW9kaWZpZXJzU3RhdGU6OlNISUZULCB+QmluZGluZ01vZGU6OlNFQVJDSCwgfkJpbmRpbmdNb2RlOjpWSTsgQWN0aW9uOjpTcGxpdERvd247CiAgICAgICAgICAgICJdIiwgTW9kaWZpZXJzU3RhdGU6OkNPTlRST0wgfCBNb2RpZmllcnNTdGF0ZTo6U0hJRlQsIH5CaW5kaW5nTW9kZTo6U0VBUkNILCB+QmluZGluZ01vZGU6OlZJOyBBY3Rpb246OlNlbGVjdE5leHRTcGxpdDsKICAgICAgICAgICAgIlsiLCBNb2RpZmllcnNTdGF0ZTo6Q09OVFJPTCB8IE1vZGlmaWVyc1N0YXRlOjpTSElGVCwgfkJpbmRpbmdNb2RlOjpTRUFSQ0gsIH5CaW5kaW5nTW9kZTo6Vkk7IEFjdGlvbjo6U2VsZWN0UHJldlNwbGl0OwogICAgICAgICkpOwogICAgfQoKICAgIGtleV9iaW5kaW5ncwp9CgojW2NmZyh0ZXN0KV0KcHViIGZuIHBsYXRmb3JtX2tleV9iaW5kaW5ncyhfOiBib29sLCBfOiBib29sLCBfOiBDb25maWdLZXlib2FyZCkgLT4gVmVjPEtleUJpbmRpbmc+IHsKICAgIHZlYyFbXQp9CgojW2NmZyh0ZXN0KV0KbW9kIHRlc3RzIHsKICAgIHVzZSBzdXBlcjo6KjsKCiAgICB1c2UgcmlvX3dpbmRvdzo6a2V5Ym9hcmQ6Ok1vZGlmaWVyc1N0YXRlOwoKICAgIHR5cGUgTW9ja0JpbmRpbmcgPSBCaW5kaW5nPHVzaXplPjsKCiAgICBpbXBsIERlZmF1bHQgZm9yIE1vY2tCaW5kaW5nIHsKICAgICAgICBmbiBkZWZhdWx0KCkgLT4gU2VsZiB7CiAgICAgICAgICAgIFNlbGYgewogICAgICAgICAgICAgICAgbW9kczogRGVmYXVsdDo6ZGVmYXVsdCgpLAogICAgICAgICAgICAgICAgYWN0aW9uOiBBY3Rpb246Ok5vbmUsCiAgICAgICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6ZW1wdHkoKSwKICAgICAgICAgICAgICAgIG5vdG1vZGU6IEJpbmRpbmdNb2RlOjplbXB0eSgpLAogICAgICAgICAgICAgICAgdHJpZ2dlcjogRGVmYXVsdDo6ZGVmYXVsdCgpLAogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfbWF0Y2hlc19pdHNlbGYoKSB7CiAgICAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZzo6ZGVmYXVsdCgpOwogICAgICAgIGxldCBpZGVudGljYWxfYmluZGluZyA9IE1vY2tCaW5kaW5nOjpkZWZhdWx0KCk7CgogICAgICAgIGFzc2VydCEoYmluZGluZy50cmlnZ2Vyc19tYXRjaCgmaWRlbnRpY2FsX2JpbmRpbmcpKTsKICAgICAgICBhc3NlcnQhKGlkZW50aWNhbF9iaW5kaW5nLnRyaWdnZXJzX21hdGNoKCZiaW5kaW5nKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ19tYXRjaGVzX2RpZmZlcmVudF9hY3Rpb24oKSB7CiAgICAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZzo6ZGVmYXVsdCgpOwogICAgICAgIGxldCBkaWZmZXJlbnRfYWN0aW9uID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBhY3Rpb246IEFjdGlvbjo6Q2xlYXJIaXN0b3J5LAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBhc3NlcnQhKGJpbmRpbmcudHJpZ2dlcnNfbWF0Y2goJmRpZmZlcmVudF9hY3Rpb24pKTsKICAgICAgICBhc3NlcnQhKGRpZmZlcmVudF9hY3Rpb24udHJpZ2dlcnNfbWF0Y2goJmJpbmRpbmcpKTsKICAgIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBtb2RzX2JpbmRpbmdfcmVxdWlyZXNfc3RyaWN0X21hdGNoKCkgewogICAgICAgIGxldCBzdXBlcnNldF9tb2RzID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RzOiBNb2RpZmllcnNTdGF0ZTo6YWxsKCksCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IHN1YnNldF9tb2RzID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RzOiBNb2RpZmllcnNTdGF0ZTo6QUxULAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBhc3NlcnQhKCFzdXBlcnNldF9tb2RzLnRyaWdnZXJzX21hdGNoKCZzdWJzZXRfbW9kcykpOwogICAgICAgIGFzc2VydCEoIXN1YnNldF9tb2RzLnRyaWdnZXJzX21hdGNoKCZzdXBlcnNldF9tb2RzKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ19tYXRjaGVzX2lkZW50aWNhbF9tb2RlKCkgewogICAgICAgIGxldCBiMSA9IE1vY2tCaW5kaW5nIHsKICAgICAgICAgICAgbW9kZTogQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgYXNzZXJ0IShiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgICAgICBhc3NlcnQhKGIyLnRyaWdnZXJzX21hdGNoKCZiMSkpOwogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfd2l0aG91dF9tb2RlX21hdGNoZXNfYW55X21vZGUoKSB7CiAgICAgICAgbGV0IGIxID0gTW9ja0JpbmRpbmc6OmRlZmF1bHQoKTsKICAgICAgICBsZXQgYjIgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG1vZGU6IEJpbmRpbmdNb2RlOjpBUFBfS0VZUEFELAogICAgICAgICAgICBub3Rtb2RlOiBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgYXNzZXJ0IShiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBiaW5kaW5nX3dpdGhfbW9kZV9tYXRjaGVzX2VtcHR5X21vZGUoKSB7CiAgICAgICAgbGV0IGIxID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QVBQX0tFWVBBRCwKICAgICAgICAgICAgbm90bW9kZTogQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmc6OmRlZmF1bHQoKTsKCiAgICAgICAgYXNzZXJ0IShiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgICAgICBhc3NlcnQhKGIyLnRyaWdnZXJzX21hdGNoKCZiMSkpOwogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfbWF0Y2hlc19tb2RlcygpIHsKICAgICAgICBsZXQgYjEgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG1vZGU6IEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOIHwgQmluZGluZ01vZGU6OkFQUF9LRVlQQUQsCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QVBQX0tFWVBBRCwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgYXNzZXJ0IShiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgICAgICBhc3NlcnQhKGIyLnRyaWdnZXJzX21hdGNoKCZiMSkpOwogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfbWF0Y2hlc19wYXJ0aWFsX2ludGVyc2VjdGlvbigpIHsKICAgICAgICBsZXQgYjEgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG1vZGU6IEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOIHwgQmluZGluZ01vZGU6OkFQUF9LRVlQQUQsCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QVBQX0tFWVBBRCB8IEJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBhc3NlcnQhKGIxLnRyaWdnZXJzX21hdGNoKCZiMikpOwogICAgICAgIGFzc2VydCEoYjIudHJpZ2dlcnNfbWF0Y2goJmIxKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ19taXNtYXRjaGVzX25vdG1vZGUoKSB7CiAgICAgICAgbGV0IGIxID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKICAgICAgICBsZXQgYjIgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG5vdG1vZGU6IEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBhc3NlcnQhKCFiMS50cmlnZ2Vyc19tYXRjaCgmYjIpKTsKICAgICAgICBhc3NlcnQhKCFiMi50cmlnZ2Vyc19tYXRjaCgmYjEpKTsKICAgIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBiaW5kaW5nX21pc21hdGNoZXNfdW5yZWxhdGVkKCkgewogICAgICAgIGxldCBiMSA9IE1vY2tCaW5kaW5nIHsKICAgICAgICAgICAgbW9kZTogQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CiAgICAgICAgbGV0IGIyID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6QVBQX0tFWVBBRCwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgYXNzZXJ0ISghYjEudHJpZ2dlcnNfbWF0Y2goJmIyKSk7CiAgICAgICAgYXNzZXJ0ISghYjIudHJpZ2dlcnNfbWF0Y2goJmIxKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ19tYXRjaGVzX25vdG1vZGVzKCkgewogICAgICAgIGxldCBzdWJzZXRfbm90bW9kZXMgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG5vdG1vZGU6IEJpbmRpbmdNb2RlOjpWSSB8IEJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwogICAgICAgIGxldCBzdXBlcnNldF9ub3Rtb2RlcyA9IE1vY2tCaW5kaW5nIHsKICAgICAgICAgICAgbm90bW9kZTogQmluZGluZ01vZGU6OkFQUF9DVVJTT1IsCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CgogICAgICAgIGFzc2VydCEoc3Vic2V0X25vdG1vZGVzLnRyaWdnZXJzX21hdGNoKCZzdXBlcnNldF9ub3Rtb2RlcykpOwogICAgICAgIGFzc2VydCEoc3VwZXJzZXRfbm90bW9kZXMudHJpZ2dlcnNfbWF0Y2goJnN1YnNldF9ub3Rtb2RlcykpOwogICAgfQoKICAgICNbdGVzdF0KICAgIGZuIGJpbmRpbmdfbWF0Y2hlc19tb2RlX25vdG1vZGUoKSB7CiAgICAgICAgbGV0IGIxID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBtb2RlOiBCaW5kaW5nTW9kZTo6VkksCiAgICAgICAgICAgIG5vdG1vZGU6IEJpbmRpbmdNb2RlOjpBUFBfQ1VSU09SLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwogICAgICAgIGxldCBiMiA9IE1vY2tCaW5kaW5nIHsKICAgICAgICAgICAgbm90bW9kZTogQmluZGluZ01vZGU6OkFQUF9DVVJTT1IsCiAgICAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgICAgIH07CgogICAgICAgIGFzc2VydCEoYjEudHJpZ2dlcnNfbWF0Y2goJmIyKSk7CiAgICAgICAgYXNzZXJ0IShiMi50cmlnZ2Vyc19tYXRjaCgmYjEpKTsKICAgIH0KCiAgICAvLyAjW3Rlc3RdCiAgICAvLyBmbiBiaW5kaW5nX3RyaWdnZXJfaW5wdXQoKSB7CiAgICAvLyAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZyB7IHRyaWdnZXI6IDEzLCAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkgfTsKCiAgICAvLyAgICAgbGV0IG1vZHMgPSBiaW5kaW5nLm1vZHM7CiAgICAvLyAgICAgbGV0IG1vZGUgPSBiaW5kaW5nLm1vZGU7CgogICAgLy8gICAgIGFzc2VydCEoYmluZGluZy5pc190cmlnZ2VyZWRfYnkobW9kZSwgbW9kcywgJjEzKSk7CiAgICAvLyAgICAgYXNzZXJ0ISghYmluZGluZy5pc190cmlnZ2VyZWRfYnkobW9kZSwgbW9kcywgJjMyKSk7CiAgICAvLyB9CgogICAgLy8gI1t0ZXN0XQogICAgLy8gZm4gYmluZGluZ190cmlnZ2VyX21vZHMoKSB7CiAgICAvLyAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZyB7CiAgICAvLyAgICAgICAgIG1vZHM6IE1vZGlmaWVyc1N0YXRlOjpBTFQgfCBNb2RpZmllcnNTdGF0ZTo6U1VQRVIsCiAgICAvLyAgICAgICAgIC4uTW9ja0JpbmRpbmc6OmRlZmF1bHQoKQogICAgLy8gICAgIH07CgogICAgLy8gICAgIGxldCBzdXBlcnNldF9tb2RzID0gTW9kaWZpZXJzU3RhdGU6OmFsbCgpOwogICAgLy8gICAgIGxldCBzdWJzZXRfbW9kcyA9IE1vZGlmaWVyc1N0YXRlOjplbXB0eSgpOwoKICAgIC8vICAgICBsZXQgdCA9IGJpbmRpbmcudHJpZ2dlcjsKICAgIC8vICAgICBsZXQgbW9kZSA9IGJpbmRpbmcubW9kZTsKCiAgICAvLyAgICAgYXNzZXJ0IShiaW5kaW5nLmlzX3RyaWdnZXJlZF9ieShtb2RlLCBiaW5kaW5nLm1vZHMsICZ0KSk7CiAgICAvLyAgICAgYXNzZXJ0ISghYmluZGluZy5pc190cmlnZ2VyZWRfYnkobW9kZSwgc3VwZXJzZXRfbW9kcywgJnQpKTsKICAgIC8vICAgICBhc3NlcnQhKCFiaW5kaW5nLmlzX3RyaWdnZXJlZF9ieShtb2RlLCBzdWJzZXRfbW9kcywgJnQpKTsKICAgIC8vIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBiaW5kaW5nX3RyaWdnZXJfbW9kZXMoKSB7CiAgICAgICAgbGV0IGJpbmRpbmcgPSBNb2NrQmluZGluZyB7CiAgICAgICAgICAgIG1vZGU6IEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLAogICAgICAgICAgICAuLk1vY2tCaW5kaW5nOjpkZWZhdWx0KCkKICAgICAgICB9OwoKICAgICAgICBsZXQgdCA9IGJpbmRpbmcudHJpZ2dlcjsKICAgICAgICBsZXQgbW9kcyA9IGJpbmRpbmcubW9kczsKCiAgICAgICAgYXNzZXJ0ISghYmluZGluZy5pc190cmlnZ2VyZWRfYnkoQmluZGluZ01vZGU6OlZJLCBtb2RzLCAmdCkpOwogICAgICAgIGFzc2VydCEoYmluZGluZy5pc190cmlnZ2VyZWRfYnkoQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4sIG1vZHMsICZ0KSk7CiAgICAgICAgYXNzZXJ0IShiaW5kaW5nLmlzX3RyaWdnZXJlZF9ieSgKICAgICAgICAgICAgQmluZGluZ01vZGU6OkFMVF9TQ1JFRU4gfCBCaW5kaW5nTW9kZTo6VkksCiAgICAgICAgICAgIG1vZHMsCiAgICAgICAgICAgICZ0CiAgICAgICAgKSk7CiAgICB9CgogICAgI1t0ZXN0XQogICAgZm4gYmluZGluZ190cmlnZ2VyX25vdG1vZGVzKCkgewogICAgICAgIGxldCBiaW5kaW5nID0gTW9ja0JpbmRpbmcgewogICAgICAgICAgICBub3Rtb2RlOiBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiwKICAgICAgICAgICAgLi5Nb2NrQmluZGluZzo6ZGVmYXVsdCgpCiAgICAgICAgfTsKCiAgICAgICAgbGV0IHQgPSBiaW5kaW5nLnRyaWdnZXI7CiAgICAgICAgbGV0IG1vZHMgPSBiaW5kaW5nLm1vZHM7CgogICAgICAgIGFzc2VydCEoYmluZGluZy5pc190cmlnZ2VyZWRfYnkoQmluZGluZ01vZGU6OlZJLCBtb2RzLCAmdCkpOwogICAgICAgIGFzc2VydCEoIWJpbmRpbmcuaXNfdHJpZ2dlcmVkX2J5KEJpbmRpbmdNb2RlOjpBTFRfU0NSRUVOLCBtb2RzLCAmdCkpOwogICAgICAgIGFzc2VydCEoIWJpbmRpbmcuaXNfdHJpZ2dlcmVkX2J5KAogICAgICAgICAgICBCaW5kaW5nTW9kZTo6QUxUX1NDUkVFTiB8IEJpbmRpbmdNb2RlOjpWSSwKICAgICAgICAgICAgbW9kcywKICAgICAgICAgICAgJnQKICAgICAgICApKTsKICAgIH0KCiAgICAjW3Rlc3RdCiAgICBmbiBiaW5kaW5nc19vdmVyd3JpdGUoKSB7CiAgICAgICAgbGV0IGJpbmRpbmdzID0gYmluZGluZ3MhKAogICAgICAgICAgICBLZXlCaW5kaW5nOwogICAgICAgICAgICAicSIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpRdWl0OwogICAgICAgICAgICAiLCIsIE1vZGlmaWVyc1N0YXRlOjpTVVBFUjsgQWN0aW9uOjpDb25maWdFZGl0b3I7CiAgICAgICAgKTsKCiAgICAgICAgbGV0IGNvbmZpZ19iaW5kaW5ncyA9IHZlYyFbQ29uZmlnS2V5QmluZGluZyB7CiAgICAgICAgICAgIGtleTogU3RyaW5nOjpmcm9tKCJxIiksCiAgICAgICAgICAgIGFjdGlvbjogU3RyaW5nOjpmcm9tKCJyZWNlaXZlY2hhciIpLAogICAgICAgICAgICB3aXRoOiBTdHJpbmc6OmZyb20oInN1cGVyIiksCiAgICAgICAgICAgIGJ5dGVzOiB2ZWMhW10sCiAgICAgICAgICAgIHRleHQ6IFN0cmluZzo6ZnJvbSgiIiksCiAgICAgICAgICAgIG1vZGU6IFN0cmluZzo6ZnJvbSgiIiksCiAgICAgICAgfV07CgogICAgICAgIGxldCBuZXdfYmluZGluZ3MgPSBjb25maWdfa2V5X2JpbmRpbmdzKGNvbmZpZ19iaW5kaW5ncywgYmluZGluZ3MpOwoKICAgICAgICBhc3NlcnRfZXEhKG5ld19iaW5kaW5ncy5sZW4oKSwgMik7CiAgICAgICAgYXNzZXJ0X2VxIShuZXdfYmluZGluZ3NbMV0uYWN0aW9uLCBBY3Rpb246OlJlY2VpdmVDaGFyKTsKICAgIH0KfQoAAAAAAAAAAFX6AAAAAAAAAAAAAA", - "AQAAAAAAAAABAAAA+UcAAAAAAACRRwAAAAAAAAAAAAAAwFVA" - ] - ] - }, - { - "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context/grid.rs", - "redo_stack": - [ - [ - 242, - 1, - "insert", - { - "characters": "_" - }, - "AQAAAOs1AAAAAAAA6zUAAAAAAAABAAAAXw", - "AQAAAAAAAAABAAAA7DUAAAAAAADsNQAAAAAAAAAAAAAAAPC/" - ], - [ - 238, - 1, - "toggle_comment", - { - "block": false - }, - "AgAAAOc1AAAAAAAA6jUAAAAAAAAAAAAA5zUAAAAAAADnNQAAAAAAAAMAAAAvLyA", - "AQAAAAAAAAABAAAA9DUAAAAAAAD0NQAAAAAAAAAAAAAAAPC/" - ], - [ - 236, - 1, - "toggle_comment", - { - "block": false - }, - "AQAAAFg2AAAAAAAAWDYAAAAAAAADAAAALy8g", - "AQAAAAAAAAABAAAAbDYAAAAAAABsNgAAAAAAAAAAAAAAAPC/" - ] - ], - "settings": - { - "buffer_size": 122996, - "encoding": "UTF-8", - "line_ending": "Unix" - }, - "undo_stack": - [ - [ - 66, - 1, - "toggle_comment", - { - "block": false - }, - "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" - ], - [ - 75, - 1, - "toggle_comment", - { - "block": false - }, - "LwAAAEyLAAAAAAAATIsAAAAAAAADAAAALy8gPosAAAAAAAA+iwAAAAAAAAMAAAAvLyAriwAAAAAAACuLAAAAAAAAAwAAAC8vIAKLAAAAAAAAAosAAAAAAAADAAAALy8g3YoAAAAAAADdigAAAAAAAAMAAAAvLyCtigAAAAAAAK2KAAAAAAAAAwAAAC8vII6KAAAAAAAAjooAAAAAAAADAAAALy8gd4oAAAAAAAB3igAAAAAAAAMAAAAvLyBKigAAAAAAAEqKAAAAAAAAAwAAAC8vIAqKAAAAAAAACooAAAAAAAADAAAALy8g4IkAAAAAAADgiQAAAAAAAAMAAAAvLyCriQAAAAAAAKuJAAAAAAAAAwAAAC8vIHmJAAAAAAAAeYkAAAAAAAADAAAALy8gOYkAAAAAAAA5iQAAAAAAAAMAAAAvLyDeiAAAAAAAAN6IAAAAAAAAAwAAAC8vIKSIAAAAAAAApIgAAAAAAAADAAAALy8gaogAAAAAAABqiAAAAAAAAAMAAAAvLyAyiAAAAAAAADKIAAAAAAAAAwAAAC8vICSIAAAAAAAAJIgAAAAAAAADAAAALy8gAogAAAAAAAACiAAAAAAAAAMAAAAvLyDlhwAAAAAAAOWHAAAAAAAAAwAAAC8vIMyHAAAAAAAAzIcAAAAAAAADAAAALy8gqocAAAAAAACqhwAAAAAAAAMAAAAvLyCKhwAAAAAAAIqHAAAAAAAAAwAAAC8vIFyHAAAAAAAAXIcAAAAAAAADAAAALy8gP4cAAAAAAAA/hwAAAAAAAAMAAAAvLyAehwAAAAAAAB6HAAAAAAAAAwAAAC8vIOqGAAAAAAAA6oYAAAAAAAADAAAALy8gtIYAAAAAAAC0hgAAAAAAAAMAAAAvLyClhgAAAAAAAKWGAAAAAAAAAwAAAC8vIH2GAAAAAAAAfYYAAAAAAAADAAAALy8gaYYAAAAAAABphgAAAAAAAAMAAAAvLyBXhgAAAAAAAFeGAAAAAAAAAwAAAC8vIDiGAAAAAAAAOIYAAAAAAAADAAAALy8gGYYAAAAAAAAZhgAAAAAAAAMAAAAvLyD7hQAAAAAAAPuFAAAAAAAAAwAAAC8vINqFAAAAAAAA2oUAAAAAAAADAAAALy8gxIUAAAAAAADEhQAAAAAAAAMAAAAvLyCthQAAAAAAAK2FAAAAAAAAAwAAAC8vIHGFAAAAAAAAcYUAAAAAAAADAAAALy8gYoUAAAAAAABihQAAAAAAAAMAAAAvLyBEhQAAAAAAAESFAAAAAAAAAwAAAC8vICmFAAAAAAAAKYUAAAAAAAADAAAALy8gEoUAAAAAAAAShQAAAAAAAAMAAAAvLyDyhAAAAAAAAPKEAAAAAAAAAwAAAC8vIKmEAAAAAAAAqYQAAAAAAAADAAAALy8gmoQAAAAAAACahAAAAAAAAAMAAAAvLyA", - "AQAAAAAAAAABAAAAmoQAAAAAAABRiwAAAAAAAAAAAAAAAPC/" - ], - [ - 91, - 1, - "insert", - { - "characters": "\n\n" - }, - "BQAAAE82AAAAAAAAUDYAAAAAAAAAAAAAUDYAAAAAAABcNgAAAAAAAAAAAABcNgAAAAAAAF02AAAAAAAAAAAAAF02AAAAAAAAaTYAAAAAAAAAAAAAUDYAAAAAAABQNgAAAAAAAAwAAAAgICAgICAgICAgICA", - "AQAAAAAAAAABAAAATzYAAAAAAABPNgAAAAAAAP///////+9/" - ], - [ - 92, - 1, - "left_delete", - null, - "AQAAAFk2AAAAAAAAWTYAAAAAAAAEAAAAICAgIA", - "AQAAAAAAAAABAAAAXTYAAAAAAABdNgAAAAAAAAAAAAAAAPC/" - ], - [ - 93, - 1, - "insert", - { - "characters": "#" - }, - "AQAAAFk2AAAAAAAAWjYAAAAAAAAAAAAA", - "AQAAAAAAAAABAAAAWTYAAAAAAABZNgAAAAAAAAAAAAAAAPC/" - ], - [ - 103, - 1, - "insert_snippet", - { - "contents": "[$0]" - }, - "AQAAAFo2AAAAAAAAXDYAAAAAAAAAAAAA", - "AQAAAAAAAAABAAAAWjYAAAAAAABaNgAAAAAAAAAAAAAAAPC/" - ], - [ - 104, - 1, - "insert", - { - "characters": "c" - }, - "AQAAAFs2AAAAAAAAXDYAAAAAAAAAAAAA", - "AQAAAAAAAAABAAAAWzYAAAAAAABbNgAAAAAAAAAAAAAAAPC/" - ], - [ - 105, - 1, - "insert_completion", - { - "completion": "cfg", - "format": "text", - "keep_prefix": false, - "must_insert": false, - "trigger": "cfg" - }, - "AgAAAFs2AAAAAAAAWzYAAAAAAAABAAAAY1s2AAAAAAAAXjYAAAAAAAAAAAAA", - "AQAAAAAAAAABAAAAXDYAAAAAAABcNgAAAAAAAAAAAAAAAPC/" - ], - [ - 106, - 1, - "cut", - null, - "AQAAAFE2AAAAAAAAUTYAAAAAAAAPAAAAICAgICAgICAjW2NmZ10K", - "AQAAAAAAAAABAAAAXjYAAAAAAABeNgAAAAAAAAAAAAAAAPC/" - ], - [ - 110, - 1, - "left_delete", - null, - "AQAAAE82AAAAAAAATzYAAAAAAAABAAAACg", - "AQAAAAAAAAABAAAAUDYAAAAAAABQNgAAAAAAAAAAAAAAYGRA" - ] - ] - }, - { - "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context/mod.rs", - "settings": - { - "buffer_size": 40091, - "encoding": "UTF-8", - "line_ending": "Unix" - }, - "undo_stack": - [ - [ - 7, - 1, - "toggle_comment", - { - "block": false - }, - "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" - ], - [ - 8, - 1, - "toggle_comment", - { - "block": false - }, - "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" - ] - ] - } - ], - "build_system": "", - "build_system_choices": - [ - ], - "build_varint": "", - "command_palette": - { - "height": 0.0, - "last_filter": "", - "selected_items": - [ - [ - "pack", - "Package Control: Install Package" - ], - [ - "packa", - "Install Package Control" - ] - ], - "width": 0.0 - }, - "console": - { - "height": 0.0, - "history": - [ - ] - }, - "distraction_free": - { - "menu_visible": true, - "show_minimap": false, - "show_open_files": false, - "show_tabs": false, - "side_bar_visible": false, - "status_bar_visible": false - }, - "expanded_folders": - [ - "/Users/rapha/Documents/a/rio", - "/Users/rapha/Documents/a/rio/.cargo", - "/Users/rapha/Documents/a/rio/.github", - "/Users/rapha/Documents/a/rio/.github/workflows", - "/Users/rapha/Documents/a/rio/docs", - "/Users/rapha/Documents/a/rio/frontends", - "/Users/rapha/Documents/a/rio/frontends/rioterm", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/bindings", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context", - "/Users/rapha/Documents/a/rio/sugarloaf", - "/Users/rapha/Documents/a/rio/sugarloaf/examples", - "/Users/rapha/Documents/a/rio/sugarloaf/src", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text", - "/Users/rapha/Documents/a/rio/sugarloaf/src/context", - "/Users/rapha/Documents/a/rio/sugarloaf/src/layout", - "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf", - "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/compositors", - "/Users/rapha/Documents/a/rio/teletypewriter" - ], - "file_history": - [ - "/Users/rapha/Documents/a/rio/Cargo.toml", - "/Users/rapha/Documents/a/rio/.goreleaser.yaml", - "/Users/rapha/Documents/a/rio/.cargo/config.toml", - "/Users/rapha/Documents/a/rio/.github/workflows/nix-build.yml", - "/Users/rapha/Documents/a/rio/docs/docs/default-key-bindings.md", - "/Users/rapha/Documents/a/rio/misc/osx/Rio.app/Contents/Info.plist", - "/Users/rapha/Documents/a/rio/misc/windows/rio-x86_64.wxs", - "/Users/rapha/Documents/a/rio/misc/windows/rio-aarch64.wxs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/font_introspector/setting.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/font_introspector/scale/bitmap/png.rs", - "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/event.rs", - "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/appkit/event.rs", - "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/windows/keyboard.rs", - "/Users/rapha/Documents/a/sugarloaf/examples/text_with_doubled_line_height.rs", - "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/window_delegate.rs", - "/Users/rapha/Documents/a/rio/docs/docs/releases.md", - "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/appkit/cursor.rs", - "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/macos/cursor.rs", - "/Users/rapha/Documents/a/rio/rio-window/src/platform_impl/linux/common/xkb/keymap.rs", - "/Users/rapha/Documents/a/rio/corcovado/src/poll.rs", - "/Users/rapha/Documents/a/rio/corcovado/src/stream.rs", - "/Users/rapha/Documents/a/rio/corcovado/src/sys/unix/io.rs", - "/Users/rapha/Documents/a/rio/copa/src/lib.rs", - "/Users/rapha/Documents/a/rio/corcovado/src/sys/unix/eventedfd.rs", - "/Users/rapha/Documents/a/rio/corcovado/src/timer.rs", - "/Users/rapha/Documents/a/rio/corcovado/test/mod.rs", - "/Users/rapha/Documents/a/rio/teletypewriter/src/unix/mod.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/config/colors/term.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/grid/mod.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/search.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/bindings/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/screen/hint.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/Cargo.toml", - "/Users/rapha/Documents/a/rio/sugarloaf/Cargo.toml", - "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/render_data.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/glyph/section/refed.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/image_cache/cache.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/image_cache/glyph.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/builder.rs", - "/Users/rapha/Documents/a/rio/Makefile", - "/Users/rapha/Documents/a/rio/rio-backend/src/config/keyboard.rs", - "/Users/rapha/Documents/a/rio/docs/docs/install/macos.md", - "/Users/rapha/Documents/a/rio/docs/docs/install/windows.md", - "/Users/rapha/Documents/a/rio/sugarloaf/src/font/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/compositors/advanced.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/builder.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/font_introspector/internal/head.rs", - "/Users/rapha/Documents/a/rio/.github/workflows/nightly.yml", - "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/state.rs", - "/Users/rapha/.config/rio/config.toml", - "/Users/rapha/Documents/a/rio/NOTES", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/screen/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/sequencer.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/text.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/layout_data.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/compositor.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/font/fallbacks/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/main.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/global.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/menu.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/menubar.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/router/window/mod.rs", - "/Users/rapha/Documents/a/winit/src/platform/macos.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/ui/appkit/menuitem.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/app/menu/macos.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/app/route.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/router/mod.rs", - "/Users/rapha/Documents/a/rio/CHANGELOG.md", - "/Users/rapha/Documents/a/rio/.gitignore", - "/Users/rapha/Documents/a/rio/misc/windows/rio.wxs", - "/Users/rapha/Documents/a/rio/.github/workflows/release.yml", - "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/grid/row.rs", - "/Users/rapha/Documents/a/rio/rio-backend/Cargo.toml", - "/Users/rapha/Documents/a/rio/rio-backend/src/config/window.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/event/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/primitives.rs", - "/Users/rapha/Documents/a/rio/wa/src/native/macos.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/state/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/platform/mod.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/crosswords/vi_mode.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/selection.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/routes/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/scheduler.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/constants.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/watcher.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/mouse/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/cross-winit/src/screen/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/context/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/routes/assistant.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/routes/dialog.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/routes/welcome.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/app/mod.rs", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src/state/navigation.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/graphics.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/layer/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/core.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/lib.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/ansi/sixel.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/ansi/graphics.rs", - "/Users/rapha/Documents/a/rio/rio-backend/src/performer/handler.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/core/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/pipeline.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rect/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/text/glyph/layout/font.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/glyph/layout/font.rs", - "/Users/rapha/Documents/a/rio/wa/src/event.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/image_cache/mod.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/sugarloaf/tree.rs", - "/Users/rapha/Documents/a/rio/wa/src/native.rs", - "/Users/rapha/Documents/a/rio/wa/src/lib.rs", - "/Users/rapha/Documents/a/rio/wa/src/app/macos.rs", - "/Users/rapha/Documents/a/rio/corcovado/src/sys/unix/mod.rs", - "/Users/rapha/Documents/a/rio/corcovado/src/lib.rs", - "/Users/rapha/Documents/a/rio/docs/versioned_docs/version-0.0.x/install/macos.md", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/util/atomic.rs", - "/Users/rapha/Documents/a/rio/rust-toolchain.toml", - "/Users/rapha/Documents/a/rio/sugarloaf/src/font/loader/mod.rs", - "/Users/rapha/Documents/a/rio/corcovado/src/io.rs", - "/Users/rapha/Documents/a/rio/sugarloaf/src/font/fonts.rs", - "/Users/rapha/Documents/a/rio/corcovado/src/sys/unix/uio.rs" - ], - "find": - { - "height": 43.0 - }, - "find_in_files": - { - "height": 104.0, - "where_history": - [ - "/Users/rapha/Documents/a/rio/sugarloaf/src,", - "/Users/rapha/Documents/a/rio/sugarloaf/src/layout,", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text,", - "/Users/rapha/Documents/a/rio/sugarloaf/src/layout,", - "/Users/rapha/Documents/a/rio/sugarloaf,", - "/Users/rapha/Documents/a/rio/frontends,", - "/Users/rapha/Documents/a/rio,", - "/Users/rapha/Documents/a/rio/rio-backend,", - "/Users/rapha/Documents/a/rio/frontends/rioterm/src,", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components,", - "/Users/rapha/Documents/a/rio/wa/src,", - "/Users/rapha/Documents/a/rio/sugarloaf/src,", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components,", - "/Users/rapha/Documents/a/rio/sugarloaf/src,", - "/Users/rapha/Documents/a/rio/sugarloaf/src/components,", - "/Users/rapha/Documents/a/rio/sugarloaf/src,", - "/Users/rapha/Documents/a/rio/corcovado/src," - ] - }, - "find_state": - { - "case_sensitive": false, - "find_history": - [ - "create_mock_context", - "create_mock_context(", - "create_mock_context", - "{},\n", - "request_resize", - "val.me", - "val.", - "request_resize", - "messenger", - "self.inner[index].val.messenger", - "request_resize", - "test", - "request_resize", - "resize", - "test_resize", - "Toggle VI Mode ", - "ToggleViMode", - "platform_key_bindings", - "ToggleViMode", - "SearchForward", - "ToggleViMode", - "free", - "check", - "draw_layout", - "SugarCursor", - "cursor", - "FragmentStyleDecoration", - "layout", - "update_dimensions", - "dimensions", - "fetch_dimensions", - "line_height", - "ascent", - "fetch_dimensions", - "rect", - "line_h", - "2.2", - "", - "try_cursor_from_selector", - "et cls = NSCursor::class();", - "'a, ", - "a, ", - "rio", - "0xa", - "KeyCode::KeyV => Some(0x09),", - "contentRectForFrameRect", - "surface_position", - "v0.2.0", - "0.2.1", - "x86_64", - "1.15", - "clear", - "IS_MACOS", - "quan", - "famil", - "SugarTree", - "current", - " as usize", - "HashMap", - "HashSet", - "promoted", - "fonts_to_load", - "FontSource::Extension", - "id", - "isbn", - "promote", - "HashSet", - "Vec", - "Vec", - "shape", - "shape_item", - "upsert", - "HashSet", - "", - "Vec<(", - "Vec<", - ".clone()", - "font_data", - "fallbacks", - "fonts_to_load", - "scale =", - "needs_bidi", - "last_offset", - "needs_bidi", - "resolve", - "RenderData", - "render_data", - "as u32", - "u32, PathBuf", - "u32", - "load_from_font_source", - "PathBuf", - "Vec", - "HashSet", - "fonts_to_load", - "u32", - "HashSet", - "[u32]", - "fonts_to_load", - "ParagraphBuilder", - "FontDataExtensionVal", - "render_data", - "process_from_cache", - "next_", - "Borrow", - "Cow", - "IndexMut", - "font_by_id", - "as_ref", - "arc<", - "unwrap(", - "font_data_extension", - "FontLibraryData", - "FontLibrary", - "Font", - "[", - "load_from_font_source", - "font_data_extension", - "load_from_font_source", - "load_fon", - "droppa", - "hit", - "FontLibrary", - "FontDataExtension", - "Lazy", - "data:" - ], - "highlight": true, - "in_selection": false, - "preserve_case": false, - "regex": false, - "replace_history": - [ - "use_wa" - ], - "reverse": false, - "scrollbar_highlights": true, - "show_context": true, - "use_buffer2": true, - "use_gitignore": true, - "whole_word": false, - "wrap": true - }, - "folders": - [ - { - "path": "/Users/rapha/Documents/a/rio" - } - ], - "groups": - [ - { - "sheets": - [ - { - "buffer": 0, - "file": "/Users/rapha/Documents/a/rio/NOTES", - "semi_transient": false, - "settings": - { - "buffer_size": 565, - "regions": - { - }, - "selection": - [ - [ - 115, - 115 - ] - ], - "settings": - { - "syntax": "Packages/Text/Plain text.tmLanguage" - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "stack_index": 9, - "stack_multiselect": false, - "type": "text" - }, - { - "buffer": 1, - "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/components/rich_text/mod.rs", - "semi_transient": false, - "settings": - { - "buffer_size": 22099, - "regions": - { - }, - "selection": - [ - [ - 16860, - 16860 - ] - ], - "settings": - { - "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", - "tab_size": 4, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "stack_index": 5, - "stack_multiselect": false, - "type": "text" - }, - { - "buffer": 2, - "file": "/Users/rapha/Documents/a/rio/pkgRio.nix", - "semi_transient": false, - "settings": - { - "buffer_size": 2578, - "regions": - { - }, - "selection": - [ - [ - 61, - 61 - ] - ], - "settings": - { - "syntax": "Packages/Text/Plain text.tmLanguage", - "tab_size": 2, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "stack_index": 4, - "stack_multiselect": false, - "type": "text" - }, - { - "buffer": 3, - "file": "/Users/rapha/Documents/a/rio/sugarloaf/examples/line_height.rs", - "semi_transient": false, - "settings": - { - "buffer_size": 11510, - "regions": - { - }, - "selection": - [ - [ - 11510, - 11510 - ] - ], - "settings": - { - "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", - "tab_size": 4, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "stack_index": 6, - "stack_multiselect": false, - "type": "text" - }, - { - "buffer": 4, - "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/layout/content.rs", - "semi_transient": false, - "settings": - { - "buffer_size": 19461, - "regions": - { - }, - "selection": - [ - [ - 785, - 796 - ], - [ - 5883, - 5894 - ] - ], - "settings": - { - "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", - "tab_size": 4, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "stack_index": 7, - "stack_multiselect": false, - "type": "text" - }, - { - "buffer": 5, - "file": "/Users/rapha/Documents/a/rio/sugarloaf/src/lib.rs", - "semi_transient": false, - "settings": - { - "buffer_size": 718, - "regions": - { - }, - "selection": - [ - [ - 336, - 336 - ] - ], - "settings": - { - "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", - "tab_size": 4, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "stack_index": 8, - "stack_multiselect": false, - "type": "text" - }, - { - "buffer": 6, - "file": "/Users/rapha/Documents/a/rio/sugarloaf/Cargo.toml", - "semi_transient": false, - "settings": - { - "buffer_size": 6744, - "regions": - { - }, - "selection": - [ - [ - 496, - 500 - ] - ], - "settings": - { - "syntax": "Packages/Text/Plain text.tmLanguage", - "tab_size": 4, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 0.0, - "zoom_level": 1.0 - }, - "stack_index": 3, - "stack_multiselect": false, - "type": "text" - }, - { - "buffer": 7, - "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/bindings/mod.rs", - "semi_transient": false, - "settings": - { - "buffer_size": 64085, - "regions": - { - }, - "selection": - [ - [ - 18425, - 18321 - ] - ], - "settings": - { - "allow_quiet_save": true, - "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", - "tab_size": 4, - "translate_tabs_to_spaces": true - }, - "translation.x": 28.5, - "translation.y": 12550.0, - "zoom_level": 1.0 - }, - "stack_index": 2, - "stack_multiselect": false, - "type": "text" - }, - { - "buffer": 8, - "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context/grid.rs", - "semi_transient": false, - "settings": - { - "buffer_size": 122996, - "regions": - { - }, - "selection": - [ - [ - 84155, - 84174 - ] - ], - "settings": - { - "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", - "tab_size": 4, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 52336.0, - "zoom_level": 1.0 - }, - "stack_index": 1, - "stack_multiselect": false, - "type": "text" - }, - { - "buffer": 9, - "file": "/Users/rapha/Documents/a/rio/frontends/rioterm/src/context/mod.rs", - "selected": true, - "semi_transient": false, - "settings": - { - "buffer_size": 40091, - "regions": - { - }, - "selection": - [ - [ - 5419, - 5438 - ] - ], - "settings": - { - "syntax": "Packages/Rust Enhanced/RustEnhanced.sublime-syntax", - "tab_size": 4, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 4076.0, - "zoom_level": 1.0 - }, - "stack_index": 0, - "stack_multiselect": false, - "type": "text" - } - ] - } - ], - "incremental_find": - { - "height": 31.0 - }, - "input": - { - "height": 43.0 - }, - "layout": - { - "cells": - [ - [ - 0, - 0, - 1, - 1 - ] - ], - "cols": - [ - 0.0, - 1.0 - ], - "rows": - [ - 0.0, - 1.0 - ] - }, - "menu_visible": true, - "output.find_results": - { - "height": 0.0 - }, - "pinned_build_system": "", - "project": "", - "replace": - { - "height": 58.0 - }, - "save_all_on_build": true, - "select_file": - { - "height": 0.0, - "last_filter": "", - "selected_items": - [ - [ - "docs/docs/default-key-bindings.md", - "docs/docs/default-key-bindings.md" - ], - [ - "Cargo.toml", - "Cargo.toml" - ], - [ - ".cargo/config.toml", - ".cargo/config.toml" - ], - [ - "scale/bitmap/png.rs", - "sugarloaf/src/font_introspector/scale/bitmap/png.rs" - ], - [ - "setting", - "sugarloaf/src/font_introspector/setting.rs" - ], - [ - "macos/cu", - "rio-window/src/platform_impl/macos/cursor.rs" - ], - [ - "appkit/cursor.rs", - "rio-window/src/platform_impl/macos/appkit/cursor.rs" - ], - [ - "xkb/keymap.rs", - "rio/rio-window/src/platform_impl/linux/common/xkb/keymap.rs" - ], - [ - "macos/eve", - "rio/rio-window/src/platform_impl/macos/event.rs" - ], - [ - "appkit/event.rs", - "rio/rio-window/src/platform_impl/macos/appkit/event.rs" - ], - [ - "windows/keyboard.rs", - "rio/rio-window/src/platform_impl/windows/keyboard.rs" - ], - [ - "awindow_delegate.rs", - "rio/rio-window/src/platform_impl/macos/window_delegate.rs" - ], - [ - "grid/ro", - "rio-backend/src/crosswords/grid/row.rs" - ], - [ - "grid/mod", - "rio-backend/src/crosswords/grid/mod.rs" - ], - [ - "", - "frontends/rioterm/src/app/mod.rs" - ], - [ - "rich_text/uti", - "sugarloaf/src/components/rich_text/util/atomic.rs" - ], - [ - "corcovado/src/po", - "corcovado/src/poll.rs" - ], - [ - "context/m", - "sugarloaf/src/context/mod.rs" - ] - ], - "width": 0.0 - }, - "select_project": - { - "height": 0.0, - "last_filter": "", - "selected_items": - [ - ], - "width": 0.0 - }, - "select_symbol": - { - "height": 0.0, - "last_filter": "", - "selected_items": - [ - ], - "width": 0.0 - }, - "selected_group": 0, - "settings": - { - }, - "show_minimap": true, - "show_open_files": false, - "show_tabs": true, - "side_bar_visible": true, - "side_bar_width": 299.0, - "status_bar_visible": true, - "template_settings": - { - } -} From ef6ea9b44ebcd516c8d235d3a7cd077506995bae Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 22:12:38 -0300 Subject: [PATCH 18/20] create_mock_context and create_dead_context --- frontends/rioterm/src/context/mod.rs | 42 ++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index 09343c3668..5e7ebc1a2c 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -181,7 +181,42 @@ pub struct ContextManager { pub titles: ContextManagerTitles, } -pub fn create_mock_context( +pub fn create_dead_context( + event_proxy: T, + window_id: WindowId, + route_id: usize, + rich_text_id: usize, + dimension: ContextDimension, +) -> Context { + let terminal = Crosswords::new( + dimension, + CursorShape::Block, + event_proxy, + window_id, + route_id, + ); + let terminal: Arc>> = Arc::new(FairMutex::new(terminal)); + let (sender, _receiver) = corcovado::channel::channel(); + + Context { + route_id, + #[cfg(not(target_os = "windows"))] + main_fd: Arc::new(-1), + #[cfg(not(target_os = "windows"))] + shell_pid: 1, + messenger: Messenger::new(sender), + renderable_content: RenderableContent::new(Cursor::default()), + terminal, + rich_text_id, + dimension, + ime: Ime::new(), + } +} + +#[cfg(test)] +pub fn create_mock_context< + T: rio_backend::event::EventListener + Clone + std::marker::Send + 'static, +>( event_proxy: T, window_id: WindowId, route_id: usize, @@ -210,7 +245,8 @@ pub fn create_mock_context ContextManager { window_id, ); - create_mock_context( + create_dead_context( event_proxy.clone(), window_id, route_id, From 7dc1143a796585d871c4fe34bfb45f73e042fd47 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 22:13:16 -0300 Subject: [PATCH 19/20] ok, move back max-jobs since is so slow --- .github/workflows/nix-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index bd4c5f2b3f..36f4d908b0 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -24,4 +24,4 @@ jobs: - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - uses: DeterminateSystems/flake-checker-action@main - - run: nix build + - run: nix build --max-jobs auto --build-max-jobs auto --print-build-logs From 06dac19b3edb58cbc30198303ebe3393f381d925 Mon Sep 17 00:00:00 2001 From: Raphael Amorim Date: Sat, 21 Dec 2024 22:16:54 -0300 Subject: [PATCH 20/20] uncomment stuff --- frontends/rioterm/src/context/grid.rs | 5124 ++++++++++++------------- frontends/rioterm/src/context/mod.rs | 26 - 2 files changed, 2562 insertions(+), 2588 deletions(-) diff --git a/frontends/rioterm/src/context/grid.rs b/frontends/rioterm/src/context/grid.rs index 9a45fb344c..9846913777 100644 --- a/frontends/rioterm/src/context/grid.rs +++ b/frontends/rioterm/src/context/grid.rs @@ -1021,2566 +1021,2566 @@ pub mod test { ); } - // #[test] - // fn test_split_right() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 1200.0, - // 800.0, - // SugarDimensions { - // scale: 1., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 85); - // assert_eq!(context_dimension.lines, 100); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - // grid.split_right(second_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [600., 0.0] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - // ] - // ); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [600.0, 0.0] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [900.0, 0.0] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), - // ] - // ); - // } - - // #[test] - // fn test_split_right_with_margin() { - // let margin = Delta { - // x: 20., - // top_y: 30., - // bottom_y: 40., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // })] - // ); - // grid.split_right(second_context); - - // /* - // > before split: - // 20 (600/20) - // |------| - - // Available width should compute with margin - // so should be 600 - 20 = 580, then will be: - // 289 + 4 (PADDING) + 290 - - // > after split: - // 10 (289/0) (4) (290/10) - // |----------|----------| - - // Margin should be splitted between first columns - // items and last columns items - // */ - - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 290.); - // assert_eq!(contexts[1].val.dimension.margin.x, 10.); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [167.0, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [145.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [312.0, margin.top_y], [1.0, 300.0]), - // ] - // ); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [167.0, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [65.5, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [232.5, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [236.5, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [236.5, 330.0], [67.5, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [304.0, margin.top_y], [1.0, 300.0]), - // ] - // ); - - // // Last context should be updated with half of x - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 131.); - // assert_eq!(contexts[1].val.dimension.margin.x, 0.); - // assert_eq!(contexts[2].val.dimension.width, 135.); - // assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.select_prev_split(); - // grid.split_right(fourth_context); - - // // If the split right happens in not the last - // // then should not update margin to half of x - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 51.5); - // assert_eq!(contexts[1].val.dimension.margin.x, 0.); - // assert_eq!(contexts[3].val.dimension.width, 55.5); - // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - - // // 2 is the last one - // assert_eq!(contexts[2].val.dimension.width, 135.0); - // assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [167.0, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [25.75, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: fourth_context_id, - // position: [196.75, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.0], [27.75, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [228.5, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.0], [67.5, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), - // ] - // ); - // } - - // #[test] - // fn test_split_right_with_margin_inside_parent() { - // let margin = Delta { - // x: 20., - // top_y: 30., - // bottom_y: 40., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // })] - // ); - - // let (third_context, _third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, _fourth_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fifth_context, _fifth_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(second_context); - // grid.select_prev_split(); - // grid.split_down(third_context); - // grid.split_right(fourth_context); - // grid.split_right(fifth_context); - - // // If the split right happens in not the last - // // then should not update margin to half of x - - // assert_eq!(grid.current_index(), 4); - - // // |1.--------------|2.------------| - // // |3.----|4.--|5.--|--------------| - // let contexts = grid.contexts(); - // assert_eq!(contexts.len(), 5); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 290.); - // assert_eq!(contexts[1].val.dimension.margin.x, 10.); - // assert_eq!(contexts[2].val.dimension.width, 129.0); - // assert_eq!(contexts[2].val.dimension.margin.x, 0.); - // assert_eq!(contexts[3].val.dimension.width, 52.5); - // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - // assert_eq!(contexts[4].val.dimension.width, 56.5); - - // // Fifth context should not have any margin x - // // TODO: - // // assert_eq!(contexts[4].val.dimension.margin.x, 0.); - - // grid.remove_current(); - // assert_eq!(grid.current_index(), 3); - // let contexts = grid.contexts(); - // assert_eq!(contexts[1].val.dimension.margin.x, 10.); - // // Fourth context should not have any margin x - // // TODO: - // // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - // } - - // #[test] - // fn test_split_down_with_margin_inside_parent() { - // let margin = Delta { - // x: 20., - // top_y: 30., - // bottom_y: 40., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 1., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (third_context, third_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 4; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fifth_context, fifth_context_id) = { - // let rich_text_id = 5; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // })] - // ); - - // grid.split_down(second_context); - // grid.split_down(third_context); - // grid.split_right(fourth_context); - // grid.select_prev_split(); - // grid.select_prev_split(); - // let current_index = grid.current_index(); - // let contexts = grid.contexts(); - // assert_eq!(contexts[current_index].val.rich_text_id, second_context_id); - // grid.split_right(fifth_context); - - // // If the split right happens in not the last - // // then should not update margin to half of x - - // assert_eq!(grid.current_index(), 4); - - // // |1.--------------| - // // |2.------|5.-----| - // // |3.------|4.-----| - // let contexts = grid.contexts(); - // assert_eq!(contexts.len(), 5); - - // assert_eq!(contexts[0].val.rich_text_id, first_context_id); - // assert_eq!(contexts[0].val.dimension.height, 298.); - // assert_eq!(contexts[0].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[0].val.dimension.margin.bottom_y, 0.); - // let first_down = contexts[0].down; - // assert_eq!(first_down, Some(1)); - // assert_eq!( - // contexts[first_down.unwrap_or_default()].val.rich_text_id, - // second_context_id - // ); - - // assert_eq!(contexts[1].val.rich_text_id, second_context_id); - // assert_eq!(contexts[1].val.dimension.height, 148.); - // assert_eq!(contexts[1].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[1].val.dimension.margin.bottom_y, 0.); - - // assert_eq!(contexts[4].val.rich_text_id, fifth_context_id); - // assert_eq!(contexts[4].val.dimension.height, 148.0); - // assert_eq!(contexts[4].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[4].val.dimension.margin.bottom_y, 0.); - - // assert_eq!(contexts[2].val.rich_text_id, third_context_id); - // assert_eq!(contexts[2].val.dimension.height, 150.0); - // assert_eq!(contexts[2].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[2].val.dimension.margin.bottom_y, 40.); - - // assert_eq!(contexts[3].val.rich_text_id, fourth_context_id); - // assert_eq!(contexts[3].val.dimension.height, 150.0); - // assert_eq!(contexts[3].val.dimension.margin.top_y, 0.); - // assert_eq!(contexts[3].val.dimension.margin.bottom_y, 40.); - - // // Fifth context should not have any margin x - // // TODO: Removal - // // grid.remove_current(); - // } - - // #[test] - // // https://github.com/raphamorim/rio/issues/760 - // fn test_split_issue_760() { - // let width = 1200.; - // let height = 800.; - - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // width, - // height, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 85); - // assert_eq!(context_dimension.lines, 100); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - // grid.split_down(second_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [0.0, 202.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - // ] - // ); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, first_context_id); - // assert_eq!(grid.current_index(), 0); - // grid.split_right(third_context); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // assert_eq!(grid.current_index(), 2); - - // let contexts = grid.contexts(); - - // let scaled_padding = PADDING * contexts[0].val.dimension.dimension.scale; - - // // Check their respective width - // assert_eq!( - // contexts[0].val.dimension.width, - // (width / 2.) - scaled_padding - // ); - // assert_eq!(contexts[1].val.dimension.width, width); - // assert_eq!(contexts[2].val.dimension.width, width / 2.); - - // // Check their respective height - // let top_height = (height / 2.) - scaled_padding; - // assert_eq!(contexts[0].val.dimension.height, top_height); - // assert_eq!(contexts[1].val.dimension.height, height / 2.); - // assert_eq!(contexts[2].val.dimension.height, top_height); - - // // [RichText(RichText { id: 0, position: [0.0, 0.0] }), - // // Rect(Rect { position: [298.0, 0.0], color: [0.0, 0.0, 1.0, 0.0], size: [1.0, 396.0] }), - // // RichText(RichText { id: 2, position: [302.0, 0.0] }), - // // Rect(Rect { position: [0.0, 198.0], color: [0.0, 0.0, 1.0, 0.0], size: [596.0, 1.0] }), - // // RichText(RichText { id: 1, position: [0.0, 202.0] })] - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [298.0, 1.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [0.0, 202.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [298.0, 0.0], [1.0, 198.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [302.0, 0.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [302.0, 198.0], [300.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [602.0, 0.0], [1.0, 198.0]), - // ] - // ); - // } - - // #[test] - // fn test_remove_right_with_margin() { - // let margin = Delta { - // x: 20., - // top_y: 30., - // bottom_y: 40., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // })] - // ); - // grid.split_right(second_context); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - - // let first_expected_dimension = (286., 0.); - // let second_expected_dimension = (131., 0.); - // let third_expected_dimension = (135., 10.); - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); - // assert_eq!( - // contexts[0].val.dimension.margin.x, - // first_expected_dimension.1 - // ); - // assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); - // assert_eq!( - // contexts[1].val.dimension.margin.x, - // second_expected_dimension.1 - // ); - // assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); - // assert_eq!( - // contexts[2].val.dimension.margin.x, - // third_expected_dimension.1 - // ); - - // grid.select_prev_split(); - // grid.split_right(fourth_context); - - // // If the split right happens in not the last - // // then should not update margin to half of x - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 51.5); - // assert_eq!(contexts[1].val.dimension.margin.x, 0.); - // assert_eq!(contexts[3].val.dimension.width, 55.5); - // assert_eq!(contexts[3].val.dimension.margin.x, 0.); - - // // 2 is the last one - // assert_eq!(contexts[2].val.dimension.width, 135.0); - // assert_eq!(contexts[2].val.dimension.margin.x, 10.); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [margin.x, margin.top_y], - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.], [143.0, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [167.0, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.], [25.75, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: fourth_context_id, - // position: [196.75, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.], [27.75, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [228.5, margin.top_y] - // }), - // create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.], [67.5, 1.0]), - // create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), - // ] - // ); - - // grid.remove_current(); - - // // If the split right happens in not the last - // // then should not update margin to half of x - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); - // assert_eq!( - // contexts[0].val.dimension.margin.x, - // first_expected_dimension.1 - // ); - // assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); - // assert_eq!( - // contexts[1].val.dimension.margin.x, - // second_expected_dimension.1 - // ); - // assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); - // assert_eq!( - // contexts[2].val.dimension.margin.x, - // third_expected_dimension.1 - // ); - - // assert_eq!(grid.current_index(), 1); - // grid.select_next_split(); - // assert_eq!(grid.current_index(), 2); - - // // Margin x should move to last - // grid.remove_current(); - // let contexts = grid.contexts(); - // assert_eq!(contexts[0].val.dimension.width, 286.); - // assert_eq!(contexts[0].val.dimension.margin.x, 0.); - // assert_eq!(contexts[1].val.dimension.width, 290.); - // assert_eq!(contexts[1].val.dimension.margin.x, 10.); - // } - - // #[test] - // fn test_split_down() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 1200.0, - // 800.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 85); - // assert_eq!(context_dimension.lines, 100); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - // grid.split_down(second_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [0.0, 202.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - // ] - // ); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_down(third_context); - - // assert_eq!( - // grid.objects(), - // vec![ - // Object::RichText(RichText { - // id: first_context_id, - // position: [0.0, 0.0], - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), - // Object::RichText(RichText { - // id: second_context_id, - // position: [0.0, 202.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 300.0], [600.0, 1.0]), - // Object::RichText(RichText { - // id: third_context_id, - // position: [0.0, 304.0] - // }), - // create_border([0.0, 0.0, 1.0, 0.0], [0.0, 404.0], [600.0, 1.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 304.0], [1.0, 100.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 98.0]), - // create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), - // ] - // ); - // } - - // #[test] - // fn test_resize() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (third_context, _third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_right(second_context); - // grid.split_down(third_context); - - // // assert_eq!( - // // grid.objects(), - // // vec![ - // // Object::RichText(RichText { - // // id: first_context_id, - // // position: [0.0, 0.0], - // // }), - // // Object::Rect(Rect { - // // position: [147.0, 0.0], - // // color: [0.0, 0.0, 0.0, 0.0], - // // size: [1.0, 300.0] - // // }), - // // Object::RichText(RichText { - // // id: second_context_id, - // // position: [149.0, 0.0] - // // }), - // // Object::Rect(Rect { - // // position: [149.0, 147.0], - // // color: [0.0, 0.0, 0.0, 0.0], - // // size: [294.0, 1.0] - // // }), - // // Object::RichText(RichText { - // // id: third_context_id, - // // position: [149.0, 149.0] - // // }), - // // ] - // // ); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // grid.resize(1200.0, 600.0); - - // // TODO: Finish test - // } - - // #[test] - // fn test_remove_right_without_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - // assert_eq!(grid.current().dimension.width, 600.); - - // grid.split_right(second_context); - - // let new_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.width, new_expected_width); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // let old_expected_width = (600. / 2.) - scaled_padding; - // assert_eq!(grid.current().dimension.width, old_expected_width); - // assert_eq!(grid.current_index(), 0); - - // grid.select_next_split(); - // assert_eq!(grid.current_index(), 1); - - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 0); - // // Whenever return to one should drop padding - // assert_eq!(grid.current().dimension.width, 600.); - // } - - // #[test] - // fn test_remove_right_with_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_right(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // let old_context_expected_width = (600. / 2.) - scaled_padding; - // assert_eq!(grid.current().dimension.width, old_context_expected_width); - // assert_eq!(grid.current_index(), 0); - - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].right, Some(1)); - // assert_eq!(grid.contexts()[current_index].down, None); - - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 0); - // // Whenever return to one should drop padding - // let expected_width = 600.; - // assert_eq!(grid.current().dimension.width, expected_width); - - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].right, None); - // assert_eq!(grid.contexts()[current_index].down, None); - // } - - // #[test] - // fn test_remove_right_with_down_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_right(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current_index(), 1); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_down(third_context); - // assert_eq!(grid.current_index(), 2); - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current().dimension.height, 300.); - - // // Move back - // grid.select_prev_split(); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current().dimension.height, 296.); - - // // Remove the current should actually make right being down - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current().dimension.height, 600.); - // } - - // #[test] - // fn test_remove_down_without_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - // assert_eq!(grid.current().dimension.width, 600.); - - // grid.split_down(second_context); - - // let new_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_expected_width); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // let old_expected_width = (600. / 2.) - scaled_padding; - // assert_eq!(grid.current().dimension.height, old_expected_width); - // assert_eq!(grid.current_index(), 0); - - // grid.select_next_split(); - // assert_eq!(grid.current_index(), 1); - - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 0); - // // Whenever return to one should drop padding - // assert_eq!(grid.current().dimension.height, 600.); - // } - - // #[test] - // fn test_remove_down_with_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, _second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_down(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_height = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // let old_context_expected_height = (600. / 2.) - scaled_padding; - // assert_eq!(grid.current().dimension.height, old_context_expected_height); - // assert_eq!(grid.current_index(), 0); - - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].down, Some(1)); - // assert_eq!(grid.contexts()[current_index].right, None); - - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 0); - // // Whenever return to one should drop padding - // let expected_height = 600.; - // assert_eq!(grid.current().dimension.height, expected_height); - - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].down, None); - // assert_eq!(grid.contexts()[current_index].right, None); - // } - - // #[test] - // fn test_remove_down_with_right_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_down(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_height = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current_index(), 1); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - // assert_eq!(grid.current_index(), 2); - // assert_eq!(grid.current().dimension.width, new_context_expected_height); - // assert_eq!(grid.current().dimension.height, 300.); - - // // Move back - // grid.select_prev_split(); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current().dimension.width, 296.); - - // // Remove the current should actually make down being down - // grid.remove_current(); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current().dimension.width, 600.); - // } - - // #[test] - // fn test_remove_context_with_parent_but_down_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (third_context, third_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 4; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fifth_context, fifth_context_id) = { - // let rich_text_id = 5; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (sixth_context, sixth_context_id) = { - // let rich_text_id = 6; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // // The test is to validate the removal of a context with parenting however - // // should move to up the down items - // // - // // Test setup - // // - // // |1.-----|.3-----|4.-----| - // // |2.-----|.5-|6.-|-------| - - // grid.split_down(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_height = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, first_context_id); - - // grid.split_right(third_context); - // assert_eq!(grid.current().rich_text_id, third_context_id); - - // grid.split_right(fourth_context); - // assert_eq!(grid.current().rich_text_id, fourth_context_id); - - // let current_index = grid.current_index(); - // assert_eq!(current_index, 3); - // assert_eq!(grid.contexts()[current_index].down, None); - - // // So far we have: - // // - // // |1.-----|.3-----|4.-----| - // // |2.-----|-------|-------| - - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // let current_index = grid.current_index(); - // assert_eq!(current_index, 2); - // assert_eq!(grid.contexts()[current_index].down, None); - - // grid.split_down(fifth_context); - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - - // grid.split_right(sixth_context); - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - - // assert_eq!(grid.current().rich_text_id, third_context_id); - - // let current_index = grid.current_index(); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // fourth_context_id - // ); - // let current_index = grid.current_index(); - // let down = grid.contexts()[current_index].down; - // assert_eq!( - // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - // fifth_context_id - // ); - // // Setup complete, now we have 3 as active as well - // // - // // |1.-----|.3-----|4.-----| - // // |2.-----|.5-|6.-|-------| - // // - // // If we remove 3 then should be - // // - // // |1.-----|.5-|6.-|4.-----| - // // |2.-----|---|---|-------| - - // grid.remove_current(); - - // // Check if current is 5 and next is 6 - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - // let current_index = grid.current_index(); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // sixth_context_id - // ); - - // // Let's go back to 1 to check if leads to 5 - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - - // assert_eq!(grid.current().rich_text_id, first_context_id); - // let current_index = grid.current_index(); - // assert_eq!(current_index, 0); - // let right = grid.contexts()[current_index].right; - // assert_eq!(right, Some(3)); - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // fifth_context_id - // ); - - // // Let's go to 6 to check if leads to 4 - // // - // // |1.-----|.5-|6.-|4.-----| - // // |2.-----|---|---|-------| - - // grid.select_next_split(); - // grid.select_next_split(); - // grid.select_next_split(); - // grid.select_next_split(); - - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - // let current_index = grid.current_index(); - // let right = grid.contexts()[current_index].right; - // assert_eq!(right, Some(2)); - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // fourth_context_id - // ); - // } - - // #[test] - // fn test_remove_context_without_parents_but_with_right_and_down_children() { - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (third_context, third_context_id) = { - // let rich_text_id = 3; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (fourth_context, fourth_context_id) = { - // let rich_text_id = 4; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.split_right(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_width = 600. / 2.; - - // assert_eq!(grid.current().dimension.width, new_context_expected_width); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // assert_eq!(grid.current_index(), 1); - - // grid.select_prev_split(); - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, second_context_id); - - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, first_context_id); - - // grid.split_down(third_context); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // assert_eq!(grid.current().dimension.width, 296.); - // assert_eq!(grid.current().dimension.height, 300.); - - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, second_context_id); - // grid.split_down(fourth_context); - - // assert_eq!(grid.current_index(), 3); - // assert_eq!(grid.current().rich_text_id, fourth_context_id); - - // grid.select_next_split(); - // assert_eq!(grid.current_index(), 0); - // assert_eq!(grid.current().rich_text_id, first_context_id); - - // // Active is 1 - // // |1.----|.2----| - // // |3.----|.4----| - - // // Remove the current should actually make right being down - // grid.remove_current(); - // let current_index = grid.current_index(); - // // Move third context to first position - // assert_eq!(current_index, 0); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // let right = grid.contexts()[current_index].right; - // let right_context = grid.contexts()[right.unwrap_or_default()].val.rich_text_id; - // assert_eq!(right_context, second_context_id); - - // // Result: - // // |3.----|.2----| - // // |------|.4----| - - // // Now let's create a more complex case - // // |3.---------|.2---------| - // // |5.-|6.-|7.-|.4---------| - - // let (fifth_context, fifth_context_id) = { - // let rich_text_id = 5; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (sixth_context, sixth_context_id) = { - // let rich_text_id = 6; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (seventh_context, seventh_context_id) = { - // let rich_text_id = 7; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_down(fifth_context); - // grid.split_right(sixth_context); - // grid.split_right(seventh_context); - - // assert_eq!(grid.current_index(), 5); - // assert_eq!(grid.current().rich_text_id, seventh_context_id); - - // // Current: - // // |3.---------|.2---------| - // // |5.-|6.-|7.-|.4---------| - // // - // // Now if we move back to 3. and remove it: - // // Should move 5, 6 and 7 to top. - // // - // // |5.-|6.-|7.-|.2---------| - // // |---|---|---|.4---------| - // grid.select_next_split(); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // let current_index = grid.current_index(); - // let down = grid.contexts()[current_index].down; - // assert_eq!( - // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - // fifth_context_id - // ); - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - - // let current_index = grid.current_index(); - // let right = grid.contexts()[current_index].right.unwrap_or_default(); - // let right_context = &grid.contexts()[right]; - // assert_eq!(right_context.val.rich_text_id, sixth_context_id); - - // // Current: - // // |5.-|6.-|7.-|.2---------| - // // |---|---|---|.4---------| - - // // Ok, let's test the reverse to right operations - // // First remove 5 and 6 - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - // let current_index = grid.current_index(); - // assert_eq!(grid.contexts()[current_index].down, None); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // seventh_context_id - // ); - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, seventh_context_id); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // second_context_id - // ); - - // // Current: - // // |7.---------|.2---------| - // // |-----------|.4---------| - - // // Now let's add many 5 and 6 as down items on 7th - // // - // // Should be: - // // |7.---------|.2---------| - // // |5.---------|.4---------| - // // |6.---------|-----------| - - // let (fifth_context, fifth_context_id) = { - // let rich_text_id = 5; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (sixth_context, sixth_context_id) = { - // let rich_text_id = 6; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_down(fifth_context); - // grid.split_down(sixth_context); - - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - // grid.select_prev_split(); - // grid.select_prev_split(); - // grid.select_prev_split(); - // assert_eq!(grid.current().rich_text_id, seventh_context_id); - - // // Next step remove 7 - // // - // // Should be: - // // |5.---------|.2---------| - // // |6.---------|.4---------| - // // |-----------|-----------| - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, fifth_context_id); - // let right = grid.contexts()[current_index].right; - // let down = grid.contexts()[current_index].down; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // second_context_id - // ); - // assert_eq!( - // grid.contexts()[down.unwrap_or_default()].val.rich_text_id, - // sixth_context_id - // ); - - // // Next step remove 5 - // // - // // Should be: - // // |6.---------|.2---------| - // // |-----------|.4---------| - // // |-----------|-----------| - - // grid.remove_current(); - // assert_eq!(grid.current().rich_text_id, sixth_context_id); - // let right = grid.contexts()[current_index].right; - // assert_eq!( - // grid.contexts()[right.unwrap_or_default()].val.rich_text_id, - // second_context_id - // ); - // assert_eq!(grid.contexts()[current_index].down, None); - // } - - // #[test] - // fn test_select_current_based_on_mouse() { - // let mut mouse = Mouse::default(); - // let margin = Delta { - // x: 0., - // top_y: 0., - // bottom_y: 0., - // }; - - // let context_dimension = ContextDimension::build( - // 600.0, - // 600.0, - // SugarDimensions { - // scale: 2., - // width: 14., - // height: 8., - // }, - // 1.0, - // Delta::::default(), - // ); - - // assert_eq!(context_dimension.columns, 42); - // assert_eq!(context_dimension.lines, 75); - - // let (first_context, first_context_id) = { - // let rich_text_id = 0; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let (second_context, second_context_id) = { - // let rich_text_id = 1; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // let mut grid = - // ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); - - // assert_eq!( - // grid.objects(), - // vec![Object::RichText(RichText { - // id: first_context_id, - // position: [0., 0.], - // })] - // ); - - // grid.select_current_based_on_mouse(&mouse); - // // On first should always return first item - // assert_eq!(grid.current_index(), 0); - - // grid.split_down(second_context); - - // assert_eq!(grid.width, 600.0); - // assert_eq!(grid.height, 600.0); - - // let new_context_expected_height = 600. / 2.; - - // assert_eq!(grid.current().dimension.height, new_context_expected_height); - // assert_eq!(grid.current_index(), 1); - - // let (third_context, third_context_id) = { - // let rich_text_id = 2; - // let route_id = 0; - // ( - // create_mock_context( - // VoidListener {}, - // WindowId::from(0), - // route_id, - // rich_text_id, - // context_dimension, - // ), - // rich_text_id, - // ) - // }; - - // grid.split_right(third_context); - // assert_eq!(grid.current_index(), 2); - // assert_eq!(grid.current().dimension.width, new_context_expected_height); - // assert_eq!(grid.current().dimension.height, 300.); - - // grid.select_current_based_on_mouse(&mouse); - // assert_eq!(grid.current_index(), 0); - // assert_eq!(grid.current().rich_text_id, 0); - - // let scaled_padding = PADDING * grid.current().dimension.dimension.scale; - // mouse.y = (new_context_expected_height + scaled_padding) as usize; - // grid.select_current_based_on_mouse(&mouse); - - // assert_eq!(grid.current_index(), 1); - // assert_eq!(grid.current().rich_text_id, second_context_id); - - // mouse.x = 304; - // grid.select_current_based_on_mouse(&mouse); - - // assert_eq!(grid.current_index(), 2); - // assert_eq!(grid.current().rich_text_id, third_context_id); - // } + #[test] + fn test_split_right() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 1200.0, + 800.0, + SugarDimensions { + scale: 1., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 85); + assert_eq!(context_dimension.lines, 100); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + grid.split_right(second_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + Object::RichText(RichText { + id: second_context_id, + position: [600., 0.0] + }), + create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [600.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + ] + ); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([1.0, 0.0, 0.0, 0.0], [0.0, 800.0], [598., 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [598.0, 0.0], [1.0, 800.0]), + Object::RichText(RichText { + id: second_context_id, + position: [600.0, 0.0] + }), + create_border([1.0, 0.0, 0.0, 0.0], [600.0, 800.0], [298.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [898.0, 0.0], [1.0, 800.0]), + Object::RichText(RichText { + id: third_context_id, + position: [900.0, 0.0] + }), + create_border([1.0, 0.0, 0.0, 0.0], [900.0, 800.0], [300.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [1200.0, 0.0], [1.0, 800.0]), + ] + ); + } + + #[test] + fn test_split_right_with_margin() { + let margin = Delta { + x: 20., + top_y: 30., + bottom_y: 40., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + })] + ); + grid.split_right(second_context); + + /* + > before split: + 20 (600/20) + |------| + + Available width should compute with margin + so should be 600 - 20 = 580, then will be: + 289 + 4 (PADDING) + 290 + + > after split: + 10 (289/0) (4) (290/10) + |----------|----------| + + Margin should be splitted between first columns + items and last columns items + */ + + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 290.); + assert_eq!(contexts[1].val.dimension.margin.x, 10.); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + }), + create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: second_context_id, + position: [167.0, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [145.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [312.0, margin.top_y], [1.0, 300.0]), + ] + ); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + }), + create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: second_context_id, + position: [167.0, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [65.5, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [232.5, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: third_context_id, + position: [236.5, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [236.5, 330.0], [67.5, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [304.0, margin.top_y], [1.0, 300.0]), + ] + ); + + // Last context should be updated with half of x + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 131.); + assert_eq!(contexts[1].val.dimension.margin.x, 0.); + assert_eq!(contexts[2].val.dimension.width, 135.); + assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.select_prev_split(); + grid.split_right(fourth_context); + + // If the split right happens in not the last + // then should not update margin to half of x + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 51.5); + assert_eq!(contexts[1].val.dimension.margin.x, 0.); + assert_eq!(contexts[3].val.dimension.width, 55.5); + assert_eq!(contexts[3].val.dimension.margin.x, 0.); + + // 2 is the last one + assert_eq!(contexts[2].val.dimension.width, 135.0); + assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + }), + create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.0], [143.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: second_context_id, + position: [167.0, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.0], [25.75, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: fourth_context_id, + position: [196.75, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.0], [27.75, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: third_context_id, + position: [228.5, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.0], [67.5, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), + ] + ); + } + + #[test] + fn test_split_right_with_margin_inside_parent() { + let margin = Delta { + x: 20., + top_y: 30., + bottom_y: 40., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + })] + ); + + let (third_context, _third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, _fourth_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fifth_context, _fifth_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(second_context); + grid.select_prev_split(); + grid.split_down(third_context); + grid.split_right(fourth_context); + grid.split_right(fifth_context); + + // If the split right happens in not the last + // then should not update margin to half of x + + assert_eq!(grid.current_index(), 4); + + // |1.--------------|2.------------| + // |3.----|4.--|5.--|--------------| + let contexts = grid.contexts(); + assert_eq!(contexts.len(), 5); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 290.); + assert_eq!(contexts[1].val.dimension.margin.x, 10.); + assert_eq!(contexts[2].val.dimension.width, 129.0); + assert_eq!(contexts[2].val.dimension.margin.x, 0.); + assert_eq!(contexts[3].val.dimension.width, 52.5); + assert_eq!(contexts[3].val.dimension.margin.x, 0.); + assert_eq!(contexts[4].val.dimension.width, 56.5); + + // Fifth context should not have any margin x + // TODO: + // assert_eq!(contexts[4].val.dimension.margin.x, 0.); + + grid.remove_current(); + assert_eq!(grid.current_index(), 3); + let contexts = grid.contexts(); + assert_eq!(contexts[1].val.dimension.margin.x, 10.); + // Fourth context should not have any margin x + // TODO: + // assert_eq!(contexts[3].val.dimension.margin.x, 0.); + } + + #[test] + fn test_split_down_with_margin_inside_parent() { + let margin = Delta { + x: 20., + top_y: 30., + bottom_y: 40., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 1., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (third_context, third_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 4; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fifth_context, fifth_context_id) = { + let rich_text_id = 5; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + })] + ); + + grid.split_down(second_context); + grid.split_down(third_context); + grid.split_right(fourth_context); + grid.select_prev_split(); + grid.select_prev_split(); + let current_index = grid.current_index(); + let contexts = grid.contexts(); + assert_eq!(contexts[current_index].val.rich_text_id, second_context_id); + grid.split_right(fifth_context); + + // If the split right happens in not the last + // then should not update margin to half of x + + assert_eq!(grid.current_index(), 4); + + // |1.--------------| + // |2.------|5.-----| + // |3.------|4.-----| + let contexts = grid.contexts(); + assert_eq!(contexts.len(), 5); + + assert_eq!(contexts[0].val.rich_text_id, first_context_id); + assert_eq!(contexts[0].val.dimension.height, 298.); + assert_eq!(contexts[0].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[0].val.dimension.margin.bottom_y, 0.); + let first_down = contexts[0].down; + assert_eq!(first_down, Some(1)); + assert_eq!( + contexts[first_down.unwrap_or_default()].val.rich_text_id, + second_context_id + ); + + assert_eq!(contexts[1].val.rich_text_id, second_context_id); + assert_eq!(contexts[1].val.dimension.height, 148.); + assert_eq!(contexts[1].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[1].val.dimension.margin.bottom_y, 0.); + + assert_eq!(contexts[4].val.rich_text_id, fifth_context_id); + assert_eq!(contexts[4].val.dimension.height, 148.0); + assert_eq!(contexts[4].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[4].val.dimension.margin.bottom_y, 0.); + + assert_eq!(contexts[2].val.rich_text_id, third_context_id); + assert_eq!(contexts[2].val.dimension.height, 150.0); + assert_eq!(contexts[2].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[2].val.dimension.margin.bottom_y, 40.); + + assert_eq!(contexts[3].val.rich_text_id, fourth_context_id); + assert_eq!(contexts[3].val.dimension.height, 150.0); + assert_eq!(contexts[3].val.dimension.margin.top_y, 0.); + assert_eq!(contexts[3].val.dimension.margin.bottom_y, 40.); + + // Fifth context should not have any margin x + // TODO: Removal + // grid.remove_current(); + } + + #[test] + // https://github.com/raphamorim/rio/issues/760 + fn test_split_issue_760() { + let width = 1200.; + let height = 800.; + + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + width, + height, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 85); + assert_eq!(context_dimension.lines, 100); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + grid.split_down(second_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + Object::RichText(RichText { + id: second_context_id, + position: [0.0, 202.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + ] + ); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, first_context_id); + assert_eq!(grid.current_index(), 0); + grid.split_right(third_context); + assert_eq!(grid.current().rich_text_id, third_context_id); + assert_eq!(grid.current_index(), 2); + + let contexts = grid.contexts(); + + let scaled_padding = PADDING * contexts[0].val.dimension.dimension.scale; + + // Check their respective width + assert_eq!( + contexts[0].val.dimension.width, + (width / 2.) - scaled_padding + ); + assert_eq!(contexts[1].val.dimension.width, width); + assert_eq!(contexts[2].val.dimension.width, width / 2.); + + // Check their respective height + let top_height = (height / 2.) - scaled_padding; + assert_eq!(contexts[0].val.dimension.height, top_height); + assert_eq!(contexts[1].val.dimension.height, height / 2.); + assert_eq!(contexts[2].val.dimension.height, top_height); + + // [RichText(RichText { id: 0, position: [0.0, 0.0] }), + // Rect(Rect { position: [298.0, 0.0], color: [0.0, 0.0, 1.0, 0.0], size: [1.0, 396.0] }), + // RichText(RichText { id: 2, position: [302.0, 0.0] }), + // Rect(Rect { position: [0.0, 198.0], color: [0.0, 0.0, 1.0, 0.0], size: [596.0, 1.0] }), + // RichText(RichText { id: 1, position: [0.0, 202.0] })] + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [298.0, 1.0]), + Object::RichText(RichText { + id: second_context_id, + position: [0.0, 202.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + create_border([0.0, 0.0, 1.0, 0.0], [298.0, 0.0], [1.0, 198.0]), + Object::RichText(RichText { + id: third_context_id, + position: [302.0, 0.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [302.0, 198.0], [300.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [602.0, 0.0], [1.0, 198.0]), + ] + ); + } + + #[test] + fn test_remove_right_with_margin() { + let margin = Delta { + x: 20., + top_y: 30., + bottom_y: 40., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [1., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + })] + ); + grid.split_right(second_context); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + + let first_expected_dimension = (286., 0.); + let second_expected_dimension = (131., 0.); + let third_expected_dimension = (135., 10.); + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); + assert_eq!( + contexts[0].val.dimension.margin.x, + first_expected_dimension.1 + ); + assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); + assert_eq!( + contexts[1].val.dimension.margin.x, + second_expected_dimension.1 + ); + assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); + assert_eq!( + contexts[2].val.dimension.margin.x, + third_expected_dimension.1 + ); + + grid.select_prev_split(); + grid.split_right(fourth_context); + + // If the split right happens in not the last + // then should not update margin to half of x + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 51.5); + assert_eq!(contexts[1].val.dimension.margin.x, 0.); + assert_eq!(contexts[3].val.dimension.width, 55.5); + assert_eq!(contexts[3].val.dimension.margin.x, 0.); + + // 2 is the last one + assert_eq!(contexts[2].val.dimension.width, 135.0); + assert_eq!(contexts[2].val.dimension.margin.x, 10.); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [margin.x, margin.top_y], + }), + create_border([1.0, 0.0, 0.0, 0.0], [20.0, 330.], [143.0, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [163.0, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: second_context_id, + position: [167.0, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [167.0, 330.], [25.75, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [192.75, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: fourth_context_id, + position: [196.75, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [196.75, 330.], [27.75, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [224.5, margin.top_y], [1.0, 300.0]), + Object::RichText(RichText { + id: third_context_id, + position: [228.5, margin.top_y] + }), + create_border([1.0, 0.0, 0.0, 0.0], [228.5, 330.], [67.5, 1.0]), + create_border([1.0, 0.0, 0.0, 0.0], [296.0, margin.top_y], [1.0, 300.0]), + ] + ); + + grid.remove_current(); + + // If the split right happens in not the last + // then should not update margin to half of x + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, first_expected_dimension.0); + assert_eq!( + contexts[0].val.dimension.margin.x, + first_expected_dimension.1 + ); + assert_eq!(contexts[1].val.dimension.width, second_expected_dimension.0); + assert_eq!( + contexts[1].val.dimension.margin.x, + second_expected_dimension.1 + ); + assert_eq!(contexts[2].val.dimension.width, third_expected_dimension.0); + assert_eq!( + contexts[2].val.dimension.margin.x, + third_expected_dimension.1 + ); + + assert_eq!(grid.current_index(), 1); + grid.select_next_split(); + assert_eq!(grid.current_index(), 2); + + // Margin x should move to last + grid.remove_current(); + let contexts = grid.contexts(); + assert_eq!(contexts[0].val.dimension.width, 286.); + assert_eq!(contexts[0].val.dimension.margin.x, 0.); + assert_eq!(contexts[1].val.dimension.width, 290.); + assert_eq!(contexts[1].val.dimension.margin.x, 10.); + } + + #[test] + fn test_split_down() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 1200.0, + 800.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 85); + assert_eq!(context_dimension.lines, 100); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 1., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + grid.split_down(second_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + Object::RichText(RichText { + id: second_context_id, + position: [0.0, 202.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 402.0], [600.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 200.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + ] + ); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_down(third_context); + + assert_eq!( + grid.objects(), + vec![ + Object::RichText(RichText { + id: first_context_id, + position: [0.0, 0.0], + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 198.0], [600.0, 1.0]), + Object::RichText(RichText { + id: second_context_id, + position: [0.0, 202.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 300.0], [600.0, 1.0]), + Object::RichText(RichText { + id: third_context_id, + position: [0.0, 304.0] + }), + create_border([0.0, 0.0, 1.0, 0.0], [0.0, 404.0], [600.0, 1.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 304.0], [1.0, 100.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 202.0], [1.0, 98.0]), + create_border([0.0, 0.0, 1.0, 0.0], [600.0, 0.0], [1.0, 198.0]), + ] + ); + } + + #[test] + fn test_resize() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (third_context, _third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_right(second_context); + grid.split_down(third_context); + + // assert_eq!( + // grid.objects(), + // vec![ + // Object::RichText(RichText { + // id: first_context_id, + // position: [0.0, 0.0], + // }), + // Object::Rect(Rect { + // position: [147.0, 0.0], + // color: [0.0, 0.0, 0.0, 0.0], + // size: [1.0, 300.0] + // }), + // Object::RichText(RichText { + // id: second_context_id, + // position: [149.0, 0.0] + // }), + // Object::Rect(Rect { + // position: [149.0, 147.0], + // color: [0.0, 0.0, 0.0, 0.0], + // size: [294.0, 1.0] + // }), + // Object::RichText(RichText { + // id: third_context_id, + // position: [149.0, 149.0] + // }), + // ] + // ); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + grid.resize(1200.0, 600.0); + + // TODO: Finish test + } + + #[test] + fn test_remove_right_without_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + assert_eq!(grid.current().dimension.width, 600.); + + grid.split_right(second_context); + + let new_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.width, new_expected_width); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + let old_expected_width = (600. / 2.) - scaled_padding; + assert_eq!(grid.current().dimension.width, old_expected_width); + assert_eq!(grid.current_index(), 0); + + grid.select_next_split(); + assert_eq!(grid.current_index(), 1); + + grid.remove_current(); + + assert_eq!(grid.current_index(), 0); + // Whenever return to one should drop padding + assert_eq!(grid.current().dimension.width, 600.); + } + + #[test] + fn test_remove_right_with_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_right(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + let old_context_expected_width = (600. / 2.) - scaled_padding; + assert_eq!(grid.current().dimension.width, old_context_expected_width); + assert_eq!(grid.current_index(), 0); + + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].right, Some(1)); + assert_eq!(grid.contexts()[current_index].down, None); + + grid.remove_current(); + + assert_eq!(grid.current_index(), 0); + // Whenever return to one should drop padding + let expected_width = 600.; + assert_eq!(grid.current().dimension.width, expected_width); + + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].right, None); + assert_eq!(grid.contexts()[current_index].down, None); + } + + #[test] + fn test_remove_right_with_down_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_right(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current_index(), 1); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_down(third_context); + assert_eq!(grid.current_index(), 2); + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current().dimension.height, 300.); + + // Move back + grid.select_prev_split(); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, second_context_id); + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current().dimension.height, 296.); + + // Remove the current should actually make right being down + grid.remove_current(); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, third_context_id); + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current().dimension.height, 600.); + } + + #[test] + fn test_remove_down_without_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + assert_eq!(grid.current().dimension.width, 600.); + + grid.split_down(second_context); + + let new_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_expected_width); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + let old_expected_width = (600. / 2.) - scaled_padding; + assert_eq!(grid.current().dimension.height, old_expected_width); + assert_eq!(grid.current_index(), 0); + + grid.select_next_split(); + assert_eq!(grid.current_index(), 1); + + grid.remove_current(); + + assert_eq!(grid.current_index(), 0); + // Whenever return to one should drop padding + assert_eq!(grid.current().dimension.height, 600.); + } + + #[test] + fn test_remove_down_with_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, _second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_down(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_height = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + let old_context_expected_height = (600. / 2.) - scaled_padding; + assert_eq!(grid.current().dimension.height, old_context_expected_height); + assert_eq!(grid.current_index(), 0); + + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].down, Some(1)); + assert_eq!(grid.contexts()[current_index].right, None); + + grid.remove_current(); + + assert_eq!(grid.current_index(), 0); + // Whenever return to one should drop padding + let expected_height = 600.; + assert_eq!(grid.current().dimension.height, expected_height); + + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].down, None); + assert_eq!(grid.contexts()[current_index].right, None); + } + + #[test] + fn test_remove_down_with_right_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_down(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_height = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current_index(), 1); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + assert_eq!(grid.current_index(), 2); + assert_eq!(grid.current().dimension.width, new_context_expected_height); + assert_eq!(grid.current().dimension.height, 300.); + + // Move back + grid.select_prev_split(); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, second_context_id); + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current().dimension.width, 296.); + + // Remove the current should actually make down being down + grid.remove_current(); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, third_context_id); + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current().dimension.width, 600.); + } + + #[test] + fn test_remove_context_with_parent_but_down_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (third_context, third_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 4; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fifth_context, fifth_context_id) = { + let rich_text_id = 5; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (sixth_context, sixth_context_id) = { + let rich_text_id = 6; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + // The test is to validate the removal of a context with parenting however + // should move to up the down items + // + // Test setup + // + // |1.-----|.3-----|4.-----| + // |2.-----|.5-|6.-|-------| + + grid.split_down(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_height = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current().rich_text_id, second_context_id); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, first_context_id); + + grid.split_right(third_context); + assert_eq!(grid.current().rich_text_id, third_context_id); + + grid.split_right(fourth_context); + assert_eq!(grid.current().rich_text_id, fourth_context_id); + + let current_index = grid.current_index(); + assert_eq!(current_index, 3); + assert_eq!(grid.contexts()[current_index].down, None); + + // So far we have: + // + // |1.-----|.3-----|4.-----| + // |2.-----|-------|-------| + + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, third_context_id); + let current_index = grid.current_index(); + assert_eq!(current_index, 2); + assert_eq!(grid.contexts()[current_index].down, None); + + grid.split_down(fifth_context); + assert_eq!(grid.current().rich_text_id, fifth_context_id); + + grid.split_right(sixth_context); + assert_eq!(grid.current().rich_text_id, sixth_context_id); + + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + + assert_eq!(grid.current().rich_text_id, third_context_id); + + let current_index = grid.current_index(); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + fourth_context_id + ); + let current_index = grid.current_index(); + let down = grid.contexts()[current_index].down; + assert_eq!( + grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + fifth_context_id + ); + // Setup complete, now we have 3 as active as well + // + // |1.-----|.3-----|4.-----| + // |2.-----|.5-|6.-|-------| + // + // If we remove 3 then should be + // + // |1.-----|.5-|6.-|4.-----| + // |2.-----|---|---|-------| + + grid.remove_current(); + + // Check if current is 5 and next is 6 + assert_eq!(grid.current().rich_text_id, fifth_context_id); + let current_index = grid.current_index(); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + sixth_context_id + ); + + // Let's go back to 1 to check if leads to 5 + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + + assert_eq!(grid.current().rich_text_id, first_context_id); + let current_index = grid.current_index(); + assert_eq!(current_index, 0); + let right = grid.contexts()[current_index].right; + assert_eq!(right, Some(3)); + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + fifth_context_id + ); + + // Let's go to 6 to check if leads to 4 + // + // |1.-----|.5-|6.-|4.-----| + // |2.-----|---|---|-------| + + grid.select_next_split(); + grid.select_next_split(); + grid.select_next_split(); + grid.select_next_split(); + + assert_eq!(grid.current().rich_text_id, sixth_context_id); + let current_index = grid.current_index(); + let right = grid.contexts()[current_index].right; + assert_eq!(right, Some(2)); + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + fourth_context_id + ); + } + + #[test] + fn test_remove_context_without_parents_but_with_right_and_down_children() { + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (third_context, third_context_id) = { + let rich_text_id = 3; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (fourth_context, fourth_context_id) = { + let rich_text_id = 4; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.split_right(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_width = 600. / 2.; + + assert_eq!(grid.current().dimension.width, new_context_expected_width); + assert_eq!(grid.current().rich_text_id, second_context_id); + assert_eq!(grid.current_index(), 1); + + grid.select_prev_split(); + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, second_context_id); + + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, first_context_id); + + grid.split_down(third_context); + assert_eq!(grid.current().rich_text_id, third_context_id); + assert_eq!(grid.current().dimension.width, 296.); + assert_eq!(grid.current().dimension.height, 300.); + + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, second_context_id); + grid.split_down(fourth_context); + + assert_eq!(grid.current_index(), 3); + assert_eq!(grid.current().rich_text_id, fourth_context_id); + + grid.select_next_split(); + assert_eq!(grid.current_index(), 0); + assert_eq!(grid.current().rich_text_id, first_context_id); + + // Active is 1 + // |1.----|.2----| + // |3.----|.4----| + + // Remove the current should actually make right being down + grid.remove_current(); + let current_index = grid.current_index(); + // Move third context to first position + assert_eq!(current_index, 0); + assert_eq!(grid.current().rich_text_id, third_context_id); + let right = grid.contexts()[current_index].right; + let right_context = grid.contexts()[right.unwrap_or_default()].val.rich_text_id; + assert_eq!(right_context, second_context_id); + + // Result: + // |3.----|.2----| + // |------|.4----| + + // Now let's create a more complex case + // |3.---------|.2---------| + // |5.-|6.-|7.-|.4---------| + + let (fifth_context, fifth_context_id) = { + let rich_text_id = 5; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (sixth_context, sixth_context_id) = { + let rich_text_id = 6; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (seventh_context, seventh_context_id) = { + let rich_text_id = 7; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_down(fifth_context); + grid.split_right(sixth_context); + grid.split_right(seventh_context); + + assert_eq!(grid.current_index(), 5); + assert_eq!(grid.current().rich_text_id, seventh_context_id); + + // Current: + // |3.---------|.2---------| + // |5.-|6.-|7.-|.4---------| + // + // Now if we move back to 3. and remove it: + // Should move 5, 6 and 7 to top. + // + // |5.-|6.-|7.-|.2---------| + // |---|---|---|.4---------| + grid.select_next_split(); + assert_eq!(grid.current().rich_text_id, third_context_id); + let current_index = grid.current_index(); + let down = grid.contexts()[current_index].down; + assert_eq!( + grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + fifth_context_id + ); + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, fifth_context_id); + + let current_index = grid.current_index(); + let right = grid.contexts()[current_index].right.unwrap_or_default(); + let right_context = &grid.contexts()[right]; + assert_eq!(right_context.val.rich_text_id, sixth_context_id); + + // Current: + // |5.-|6.-|7.-|.2---------| + // |---|---|---|.4---------| + + // Ok, let's test the reverse to right operations + // First remove 5 and 6 + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, sixth_context_id); + let current_index = grid.current_index(); + assert_eq!(grid.contexts()[current_index].down, None); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + seventh_context_id + ); + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, seventh_context_id); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + second_context_id + ); + + // Current: + // |7.---------|.2---------| + // |-----------|.4---------| + + // Now let's add many 5 and 6 as down items on 7th + // + // Should be: + // |7.---------|.2---------| + // |5.---------|.4---------| + // |6.---------|-----------| + + let (fifth_context, fifth_context_id) = { + let rich_text_id = 5; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (sixth_context, sixth_context_id) = { + let rich_text_id = 6; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_down(fifth_context); + grid.split_down(sixth_context); + + assert_eq!(grid.current().rich_text_id, sixth_context_id); + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, fifth_context_id); + grid.select_prev_split(); + grid.select_prev_split(); + grid.select_prev_split(); + assert_eq!(grid.current().rich_text_id, seventh_context_id); + + // Next step remove 7 + // + // Should be: + // |5.---------|.2---------| + // |6.---------|.4---------| + // |-----------|-----------| + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, fifth_context_id); + let right = grid.contexts()[current_index].right; + let down = grid.contexts()[current_index].down; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + second_context_id + ); + assert_eq!( + grid.contexts()[down.unwrap_or_default()].val.rich_text_id, + sixth_context_id + ); + + // Next step remove 5 + // + // Should be: + // |6.---------|.2---------| + // |-----------|.4---------| + // |-----------|-----------| + + grid.remove_current(); + assert_eq!(grid.current().rich_text_id, sixth_context_id); + let right = grid.contexts()[current_index].right; + assert_eq!( + grid.contexts()[right.unwrap_or_default()].val.rich_text_id, + second_context_id + ); + assert_eq!(grid.contexts()[current_index].down, None); + } + + #[test] + fn test_select_current_based_on_mouse() { + let mut mouse = Mouse::default(); + let margin = Delta { + x: 0., + top_y: 0., + bottom_y: 0., + }; + + let context_dimension = ContextDimension::build( + 600.0, + 600.0, + SugarDimensions { + scale: 2., + width: 14., + height: 8., + }, + 1.0, + Delta::::default(), + ); + + assert_eq!(context_dimension.columns, 42); + assert_eq!(context_dimension.lines, 75); + + let (first_context, first_context_id) = { + let rich_text_id = 0; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let (second_context, second_context_id) = { + let rich_text_id = 1; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + let mut grid = + ContextGrid::::new(first_context, margin, [0., 0., 0., 0.]); + + assert_eq!( + grid.objects(), + vec![Object::RichText(RichText { + id: first_context_id, + position: [0., 0.], + })] + ); + + grid.select_current_based_on_mouse(&mouse); + // On first should always return first item + assert_eq!(grid.current_index(), 0); + + grid.split_down(second_context); + + assert_eq!(grid.width, 600.0); + assert_eq!(grid.height, 600.0); + + let new_context_expected_height = 600. / 2.; + + assert_eq!(grid.current().dimension.height, new_context_expected_height); + assert_eq!(grid.current_index(), 1); + + let (third_context, third_context_id) = { + let rich_text_id = 2; + let route_id = 0; + ( + create_mock_context( + VoidListener {}, + WindowId::from(0), + route_id, + rich_text_id, + context_dimension, + ), + rich_text_id, + ) + }; + + grid.split_right(third_context); + assert_eq!(grid.current_index(), 2); + assert_eq!(grid.current().dimension.width, new_context_expected_height); + assert_eq!(grid.current().dimension.height, 300.); + + grid.select_current_based_on_mouse(&mouse); + assert_eq!(grid.current_index(), 0); + assert_eq!(grid.current().rich_text_id, 0); + + let scaled_padding = PADDING * grid.current().dimension.dimension.scale; + mouse.y = (new_context_expected_height + scaled_padding) as usize; + grid.select_current_based_on_mouse(&mouse); + + assert_eq!(grid.current_index(), 1); + assert_eq!(grid.current().rich_text_id, second_context_id); + + mouse.x = 304; + grid.select_current_based_on_mouse(&mouse); + + assert_eq!(grid.current_index(), 2); + assert_eq!(grid.current().rich_text_id, third_context_id); + } } diff --git a/frontends/rioterm/src/context/mod.rs b/frontends/rioterm/src/context/mod.rs index 5e7ebc1a2c..32bed74e23 100644 --- a/frontends/rioterm/src/context/mod.rs +++ b/frontends/rioterm/src/context/mod.rs @@ -247,32 +247,6 @@ pub fn create_mock_context< &config, ) .unwrap() - - // let terminal = Crosswords::new( - // dimension, - // CursorShape::Block, - // event_proxy, - // window_id, - // route_id, - // ); - // let terminal: Arc>> = Arc::new(FairMutex::new(terminal)); - // let (sender, _receiver) = corcovado::channel::channel(); - // let messenger = Messenger::new(sender); - // let renderable_content = RenderableContent::new(Cursor::default()); - - // Context { - // route_id, - // #[cfg(not(target_os = "windows"))] - // main_fd: Arc::new(-1), - // #[cfg(not(target_os = "windows"))] - // shell_pid: 1, - // messenger, - // renderable_content, - // terminal, - // rich_text_id, - // dimension, - // ime: Ime::new(), - // } } impl ContextManager {