LCOV - code coverage report
Current view: top level - gui/source/sketch - gui_sketch_result_list.c (source / functions) Coverage Total Hit
Test: crystal-facet-uml_v1.66.0_covts Lines: 0.0 % 203 0
Test Date: 2025-10-11 12:10:40 Functions: 0.0 % 6 0

            Line data    Source code
       1              : /* File: gui_sketch_result_list.c; Copyright and License: see below */
       2              : 
       3              : #include "sketch/gui_sketch_result_list.h"
       4              : #include "geometry/geometry_rectangle.h"
       5              : #include "utf8stringbuf/utf8stringbuf.h"
       6              : #include "u8/u8_trace.h"
       7              : #include "u8/u8_log.h"
       8              : #include "u8/u8_i32.h"
       9              : #include "gui_gdk.h"
      10              : 
      11              : static const int GUI_SKETCH_RESULT_LIST_PANGO_AUTO_DETECT_LENGTH = -1;  /*!< pango automatically determines the string length */
      12              : static const int GUI_SKETCH_RESULT_LIST_PANGO_UNLIMITED_WIDTH = -1;
      13              : static const int OBJ_GAP = 4;
      14              : 
      15            0 : void gui_sketch_result_list_init( gui_sketch_result_list_t *this_,
      16              :                                   const gui_resources_t *resources,
      17              :                                   gui_sketch_texture_t *texture_downloader )
      18              : {
      19            0 :     U8_TRACE_BEGIN();
      20            0 :     assert( resources != NULL );
      21            0 :     assert( texture_downloader != NULL );
      22              : 
      23              :     /* layouting information */
      24            0 :     (*this_).visible = false;
      25            0 :     shape_int_rectangle_init( &((*this_).bounds), 0, 0, 0, 0 );
      26              : 
      27              :     /* data and layouting information of search results */
      28            0 :     (*this_).requested_page = pos_scroll_page_new( 0, false /* backwards */ );
      29            0 :     pos_search_result_page_init( &((*this_).page), 0 /* buffer_start */ );
      30              : 
      31              :     /* helper classes to perform drawing */
      32            0 :     gui_sketch_style_init( &((*this_).sketch_style) );
      33            0 :     gui_sketch_marker_init( &((*this_).sketch_marker), true );
      34            0 :     (*this_).resources = resources;
      35            0 :     gui_type_resource_list_init( &((*this_).selector), resources );
      36            0 :     (*this_).texture_downloader = texture_downloader;
      37              : 
      38            0 :     U8_TRACE_END();
      39            0 : }
      40              : 
      41            0 : void gui_sketch_result_list_destroy( gui_sketch_result_list_t *this_ )
      42              : {
      43            0 :     U8_TRACE_BEGIN();
      44              : 
      45              :     /* helper classes to perform drawing */
      46            0 :     (*this_).texture_downloader = NULL;
      47            0 :     gui_type_resource_list_destroy( &((*this_).selector) );
      48            0 :     (*this_).resources = NULL;
      49            0 :     gui_sketch_marker_destroy( &((*this_).sketch_marker) );
      50            0 :     gui_sketch_style_destroy( &((*this_).sketch_style) );
      51              : 
      52              :     /* data and layouting information of search results */
      53            0 :     pos_search_result_page_destroy( &((*this_).page) );
      54              : 
      55              :     /* layouting information */
      56            0 :     shape_int_rectangle_destroy( &((*this_).bounds) );
      57              : 
      58            0 :     U8_TRACE_END();
      59            0 : }
      60              : 
      61            0 : void gui_sketch_result_list_do_layout( gui_sketch_result_list_t *this_, cairo_t *cr )
      62              : {
      63            0 :     U8_TRACE_BEGIN();
      64              : 
      65              :     /* bounds */
      66            0 :     int_fast32_t left = shape_int_rectangle_get_left( &((*this_).bounds) );
      67            0 :     uint_fast32_t width = shape_int_rectangle_get_width( &((*this_).bounds) );
      68            0 :     int_fast32_t top = shape_int_rectangle_get_top( &((*this_).bounds) );
      69            0 :     uint_fast32_t height = shape_int_rectangle_get_height( &((*this_).bounds) );
      70              : 
      71              :     /* create the font_layout */
      72              :     PangoLayout *font_layout;
      73              :     {
      74            0 :         font_layout = pango_cairo_create_layout (cr);
      75              :         const PangoFontDescription *const std_font
      76            0 :             = gui_sketch_style_get_standard_font_description( &((*this_).sketch_style ) );
      77            0 :         pango_layout_set_font_description( font_layout, std_font );
      78              :     }
      79              : 
      80              :     /* measure a previous page button heights */
      81            0 :     GdkTexture *prev_gray_icon = gui_resources_get_sketch_page_up_gray( (*this_).resources );
      82            0 :     const uint_fast32_t prev_icon_height = gdk_texture_get_height( prev_gray_icon );
      83            0 :     const uint_fast32_t prev_icon_width = gdk_texture_get_width( prev_gray_icon );
      84            0 :     const shape_int_rectangle_t prev_icon_box = (shape_int_rectangle_t) {
      85            0 :         .left = left + ( width - prev_icon_width ) / 2,
      86              :         .top = top,
      87              :         .width = prev_icon_width,
      88              :         .height = prev_icon_height };
      89            0 :     pos_search_result_page_set_button_prev_box( &((*this_).page), &prev_icon_box );
      90              : 
      91              :     /* measure a next page button heights */
      92            0 :     GdkTexture *next_gray_icon = gui_resources_get_sketch_page_down_gray( (*this_).resources );
      93            0 :     const uint_fast32_t next_icon_height = gdk_texture_get_height( next_gray_icon );
      94            0 :     const uint_fast32_t next_icon_width = gdk_texture_get_width( next_gray_icon );
      95            0 :     const shape_int_rectangle_t next_icon_box = (shape_int_rectangle_t) {
      96            0 :         .left = left + ( width - next_icon_width ) / 2,
      97            0 :         .top = top + height - next_icon_height,
      98              :         .width = next_icon_width,
      99              :         .height = next_icon_height };
     100            0 :     pos_search_result_page_set_button_next_box( &((*this_).page), &next_icon_box );
     101              : 
     102              :     /* initialize a possible result - in case the buffer is empty and the for loop later is not executed */
     103            0 :     const int32_t buffer_start = pos_search_result_page_get_buffer_start( &((*this_).page) );
     104            0 :     const uint32_t buffer_length = pos_search_result_page_get_buffer_length( &((*this_).page) );
     105            0 :     assert( buffer_length <= POS_SEARCH_RESULT_PAGE_MAX_PAGE_SIZE );
     106            0 :     const bool buffer_more_after = pos_search_result_page_get_buffer_more_after( &((*this_).page) );
     107            0 :     pos_search_result_page_set_page_start( &((*this_).page), buffer_start );  /* default value for case of empty buffer */
     108            0 :     pos_search_result_page_set_page_length( &((*this_).page), buffer_length );  /* default value for case of empty buffer */
     109            0 :     pos_search_result_page_set_has_prev_page( &((*this_).page), ( buffer_start != 0 ) );  /* default value for case of empty buffer */
     110              : 
     111              :     /* do not fully trust the consistency between (*this_).requested_page and (*this_).page. */
     112              :     /* These information come from different sources. */
     113            0 :     pos_scroll_page_trace( &((*this_).requested_page) );
     114            0 :     const int_fast32_t requested_anchor_idx = pos_scroll_page_get_anchor_index( &((*this_).requested_page) );
     115            0 :     const bool valid_anchor
     116            0 :         = (( buffer_start <= requested_anchor_idx )&&( requested_anchor_idx < ( buffer_start + buffer_length )));
     117            0 :     assert( valid_anchor || ( buffer_length == 0 ) );
     118            0 :     const int_fast32_t anchor_idx = valid_anchor ? requested_anchor_idx : buffer_start;
     119            0 :     const bool requested_backwards = pos_scroll_page_get_backwards( &((*this_).requested_page) );
     120            0 :     const bool backwards = valid_anchor ? requested_backwards : false;
     121              : 
     122              :     /* each visible element, do layout */
     123            0 :     if ( backwards )
     124              :     {
     125              :         /* y positions */
     126            0 :         int_fast32_t y_pos = shape_int_rectangle_get_bottom( &((*this_).bounds) ) - next_icon_height - OBJ_GAP;
     127            0 :         const int_fast32_t top_border = shape_int_rectangle_get_top( &((*this_).bounds) ) + prev_icon_height + OBJ_GAP;
     128            0 :         bool page_full = false;
     129            0 :         for ( int32_t index = anchor_idx; ( index >= buffer_start ) && ( ! page_full ); index -- )
     130              :         {
     131              :             pos_search_result_t *const search_result
     132            0 :                 = pos_search_result_page_get_search_result_layout_ptr( &((*this_).page), index );
     133            0 :             gui_sketch_result_list_private_layout_element( this_, search_result, &y_pos, backwards, font_layout );
     134            0 :             if ( y_pos < top_border )
     135              :             {
     136            0 :                 page_full = true;
     137              :             }
     138              :             else
     139              :             {
     140              :                 /* define the range of visible elements */
     141            0 :                 pos_search_result_page_set_page_start( &((*this_).page), index );
     142            0 :                 pos_search_result_page_set_page_length( &((*this_).page), anchor_idx - index + 1 );
     143            0 :                 pos_search_result_page_set_has_prev_page( &((*this_).page), ( index != 0 ) );
     144              :             }
     145              :         }
     146            0 :         const bool more_after_anchor = ( anchor_idx + 1 ) < ( buffer_start + buffer_length );
     147            0 :         pos_search_result_page_set_has_next_page( &((*this_).page), buffer_more_after || more_after_anchor );
     148              :     }
     149              :     else
     150              :     {
     151              :         /* y positions */
     152            0 :         int_fast32_t y_pos = shape_int_rectangle_get_top( &((*this_).bounds) ) + prev_icon_height + OBJ_GAP;
     153            0 :         const int_fast32_t bottom_border = shape_int_rectangle_get_bottom( &((*this_).bounds) ) - next_icon_height - OBJ_GAP;
     154            0 :         bool page_full = false;
     155            0 :         for ( uint32_t buffer_idx = 0; ( buffer_idx < buffer_length ) && ( ! page_full ); buffer_idx ++ )
     156              :         {
     157            0 :             const uint32_t index = buffer_start + buffer_idx;
     158              :             pos_search_result_t *const search_result
     159            0 :                 = pos_search_result_page_get_search_result_layout_ptr( &((*this_).page), index );
     160            0 :             gui_sketch_result_list_private_layout_element( this_, search_result, &y_pos, backwards, font_layout );
     161            0 :             if ( y_pos > bottom_border )
     162              :             {
     163            0 :                 page_full = true;
     164              :             }
     165              :             else
     166              :             {
     167              :                 /* define the range of visible elements */
     168            0 :                 pos_search_result_page_set_page_start( &((*this_).page), buffer_start );
     169            0 :                 pos_search_result_page_set_page_length( &((*this_).page), index - buffer_start + 1 );
     170              :             }
     171              :         }
     172            0 :         pos_search_result_page_set_has_next_page( &((*this_).page), buffer_more_after || page_full );
     173              :     }
     174              : 
     175              :     /* trace available buffer and visible page */
     176            0 :     U8_TRACE_INFO_INT_INT( "gui_sketch_result_list_do_layout: available buffer (start,len):", buffer_start, buffer_length );
     177            0 :     U8_TRACE_INFO_INT_INT( "gui_sketch_result_list_do_layout: visible page     (start,len):",
     178              :                            pos_search_result_page_get_page_start( &((*this_).page) ),
     179              :                            pos_search_result_page_get_page_length( &((*this_).page) )
     180              :                          );
     181              : 
     182              :     /* release the font_layout */
     183            0 :     g_object_unref(font_layout);
     184              : 
     185            0 :     U8_TRACE_END();
     186            0 : }
     187              : 
     188            0 : void gui_sketch_result_list_private_layout_element ( gui_sketch_result_list_t *this_,
     189              :                                                      pos_search_result_t *element,
     190              :                                                      int_fast32_t *io_y_pos,
     191              :                                                      bool upwards,
     192              :                                                      PangoLayout *font_layout )
     193              : {
     194            0 :     U8_TRACE_BEGIN();
     195            0 :     assert( NULL != element );
     196            0 :     assert( NULL != io_y_pos );
     197            0 :     assert( NULL != font_layout );
     198              : 
     199            0 :     int_fast32_t left = shape_int_rectangle_get_left( &((*this_).bounds) );
     200            0 :     uint_fast32_t width = shape_int_rectangle_get_width( &((*this_).bounds) );
     201            0 :     const data_search_result_t *result = pos_search_result_get_data_const( element );
     202              : 
     203              :     /* determine icon dimensions */
     204            0 :     const data_type_t result_type = data_search_result_get_match_type( result );
     205              :     gui_type_resource_t *const type_data
     206            0 :         = gui_type_resource_list_get_type ( &((*this_).selector), result_type );
     207            0 :     GdkTexture *const icon = gui_type_resource_get_icon( type_data );
     208            0 :     const uint_fast32_t icon_width = gdk_texture_get_width( icon );
     209            0 :     const uint_fast32_t icon_height = gdk_texture_get_height( icon );
     210              : 
     211              :     /* determine label dimensions */
     212            0 :     int_fast32_t proposed_pango_width = width - icon_width - (4*OBJ_GAP);
     213            0 :     pango_layout_set_text( font_layout,
     214              :                            data_search_result_get_match_name_const( result ),
     215              :                            GUI_SKETCH_RESULT_LIST_PANGO_AUTO_DETECT_LENGTH
     216              :                          );
     217            0 :     pango_layout_set_width(font_layout, proposed_pango_width * PANGO_SCALE );
     218              :     int text_width;
     219              :     int text_height;
     220            0 :     pango_layout_get_pixel_size(font_layout, &text_width, &text_height);
     221              : 
     222              :     /* calculate element bounds */
     223            0 :     const uint_fast32_t element_height = u8_i32_max2( icon_height, text_height );
     224            0 :     const int_fast32_t element_top = (*io_y_pos) - ( upwards ? ( OBJ_GAP + element_height ) : (-OBJ_GAP) );
     225              : 
     226              :     /* set icon dimensions */
     227            0 :     const shape_int_rectangle_t icon_box = (shape_int_rectangle_t) {
     228            0 :         .left = left + OBJ_GAP,
     229              :         .top = element_top,
     230              :         .width = icon_width,
     231              :         .height = icon_height };
     232            0 :     pos_search_result_set_icon_box( element, &icon_box );
     233              : 
     234              :     /* set label dimensions */
     235            0 :     int_fast32_t x_pos = shape_int_rectangle_get_right( &icon_box );
     236            0 :     const shape_int_rectangle_t label_box = (shape_int_rectangle_t) {
     237            0 :         .left = x_pos + OBJ_GAP,
     238              :         .top = element_top,
     239              :         .width = text_width,
     240              :         .height = text_height };
     241            0 :     pos_search_result_set_label_box( element, &label_box );
     242              : 
     243              :     /* update y_pos */
     244            0 :     *io_y_pos = ( upwards ? element_top : ( element_top + element_height ) );
     245              : 
     246            0 :     U8_TRACE_END();
     247            0 : }
     248              : 
     249            0 : void gui_sketch_result_list_draw ( gui_sketch_result_list_t *this_, const gui_marked_set_t *marker, cairo_t *cr )
     250              : {
     251            0 :     U8_TRACE_BEGIN();
     252            0 :     assert( NULL != marker );
     253            0 :     assert( NULL != cr );
     254              : 
     255            0 :     if ( (*this_).visible )
     256              :     {
     257            0 :         PangoLayout *font_layout = pango_cairo_create_layout (cr);
     258              :         {
     259              :             const PangoFontDescription *const std_font
     260            0 :                 = gui_sketch_style_get_standard_font_description( &((*this_).sketch_style ) );
     261            0 :             pango_layout_set_font_description ( font_layout, std_font );
     262              :         }
     263              : 
     264              :         /* draw icons and text */
     265            0 :         const uint32_t page_start = pos_search_result_page_get_page_start( &((*this_).page) );
     266            0 :         const uint32_t page_length = pos_search_result_page_get_page_length( &((*this_).page) );
     267            0 :         assert( page_length <= POS_SEARCH_RESULT_PAGE_MAX_PAGE_SIZE );
     268            0 :         if ( ( page_start + page_length ) == 0 )
     269              :         {
     270            0 :             const int_fast32_t left = shape_int_rectangle_get_left( &((*this_).bounds) );
     271            0 :             const int_fast32_t top = shape_int_rectangle_get_top( &((*this_).bounds) );
     272            0 :             GdkTexture *undef_icon = gui_resources_get_type_undef( (*this_).resources );
     273            0 :             const uint_fast32_t icon_width = gdk_texture_get_width ( undef_icon );
     274              : 
     275              :             /* draw text first, use the above set color and font */
     276            0 :             const GdkRGBA std_color = gui_sketch_style_get_standard_color( &((*this_).sketch_style) );
     277            0 :             cairo_set_source_rgba( cr, std_color.red, std_color.green, std_color.blue, std_color.alpha );
     278            0 :             cairo_move_to( cr, left+OBJ_GAP+icon_width, top+OBJ_GAP );
     279            0 :             pango_layout_set_text( font_layout, "no results", GUI_SKETCH_RESULT_LIST_PANGO_AUTO_DETECT_LENGTH );
     280            0 :             pango_layout_set_width(font_layout, GUI_SKETCH_RESULT_LIST_PANGO_UNLIMITED_WIDTH );
     281            0 :             pango_cairo_show_layout( cr, font_layout );
     282              : 
     283              :             /* draw the icon */
     284            0 :             const int_fast32_t x = left + OBJ_GAP;
     285            0 :             const int_fast32_t y = top + OBJ_GAP;
     286            0 :             gui_sketch_texture_draw( (*this_).texture_downloader, undef_icon, x, y, cr );
     287              :         }
     288              :         else
     289              :         {
     290              :             /* draw search results */
     291            0 :             for ( uint32_t idx = 0; idx < page_length; idx ++ )
     292              :             {
     293              :                 const pos_search_result_t *const element
     294            0 :                     = pos_search_result_page_get_search_result_layout_const( &((*this_).page), page_start + idx );
     295            0 :                 gui_sketch_result_list_private_draw_element( this_, element, marker, font_layout, cr );
     296              :             }
     297              : 
     298              :             /* draw prev and next page buttons */
     299            0 :             const gui_sketch_action_t btn_act = gui_marked_set_get_highlighted_button( marker );
     300            0 :             if ( pos_search_result_page_has_prev_page( &((*this_).page) ) )
     301              :             {
     302              :                 const shape_int_rectangle_t *const prev_box
     303            0 :                     = pos_search_result_page_get_button_prev_box_const( &((*this_).page) );
     304            0 :                 GdkTexture *const prev_icon
     305              :                     = ( btn_act == GUI_SKETCH_ACTION_PREVIOUS_PAGE )
     306            0 :                     ? gui_resources_get_sketch_page_up_bold( (*this_).resources )
     307            0 :                     : gui_resources_get_sketch_page_up_gray( (*this_).resources );
     308            0 :                 gui_sketch_texture_draw( (*this_).texture_downloader,
     309              :                                          prev_icon,
     310            0 :                                          shape_int_rectangle_get_left( prev_box ),
     311            0 :                                          shape_int_rectangle_get_top( prev_box ),
     312              :                                          cr
     313              :                                        );
     314              :             }
     315            0 :             if ( pos_search_result_page_has_next_page( &((*this_).page) ) )
     316              :             {
     317              :                 const shape_int_rectangle_t *const next_box
     318            0 :                     = pos_search_result_page_get_button_next_box_const( &((*this_).page) );
     319            0 :                 GdkTexture *const next_icon
     320              :                     = ( btn_act == GUI_SKETCH_ACTION_NEXT_PAGE )
     321            0 :                     ? gui_resources_get_sketch_page_down_bold( (*this_).resources )
     322            0 :                     : gui_resources_get_sketch_page_down_gray( (*this_).resources );
     323            0 :                 gui_sketch_texture_draw( (*this_).texture_downloader,
     324              :                                          next_icon,
     325            0 :                                          shape_int_rectangle_get_left( next_box ),
     326            0 :                                          shape_int_rectangle_get_top( next_box ),
     327              :                                          cr
     328              :                                        );
     329              :             }
     330              :         }
     331              : 
     332            0 :         g_object_unref(font_layout);
     333              :     }
     334              : 
     335            0 :     U8_TRACE_END();
     336            0 : }
     337              : 
     338            0 : void gui_sketch_result_list_private_draw_element( gui_sketch_result_list_t *this_,
     339              :                                                   const pos_search_result_t *element,
     340              :                                                   const gui_marked_set_t *marker,
     341              :                                                   PangoLayout *font_layout,
     342              :                                                   cairo_t *cr )
     343              : {
     344            0 :     U8_TRACE_BEGIN();
     345            0 :     assert( NULL != cr );
     346            0 :     assert( NULL != element );
     347            0 :     assert( NULL != marker );
     348            0 :     assert( NULL != font_layout );
     349              : 
     350            0 :     const data_search_result_t *const result = pos_search_result_get_data_const( element );
     351              : 
     352              :     /* draw marker and set color */
     353              :     {
     354              :         shape_int_rectangle_t destination_rect;
     355            0 :         shape_int_rectangle_init_by_bounds( &destination_rect,
     356              :                                             pos_search_result_get_icon_box_const(element),
     357              :                                             pos_search_result_get_label_box_const(element)
     358              :                                           );
     359              : 
     360            0 :         const data_id_t highlighted = gui_marked_set_get_highlighted( marker );
     361            0 :         gui_sketch_marker_prepare_draw( &((*this_).sketch_marker),
     362              :                                         data_search_result_get_match_id( result ),
     363              :                                         marker,
     364              :                                         destination_rect,
     365              :                                         cr
     366              :                                       );
     367            0 :         if ( data_id_equals( &highlighted, data_search_result_get_diagram_id_const( result ) ) )
     368              :         {
     369            0 :             const GdkRGBA high_color = gui_sketch_style_get_highlight_color( &((*this_).sketch_style) );
     370            0 :             cairo_set_source_rgba( cr, high_color.red, high_color.green, high_color.blue, high_color.alpha );
     371              :         }
     372              : 
     373            0 :         shape_int_rectangle_destroy( &destination_rect );
     374              :     }
     375              : 
     376              :     /* draw text first, use the above set color and font */
     377              :     {
     378              :         /* what to draw */
     379            0 :         const char *const label = data_search_result_get_match_name_const( result );
     380              : 
     381              :         /* where to draw to */
     382              :         const shape_int_rectangle_t *const label_box
     383            0 :             = pos_search_result_get_label_box_const( element );
     384              : 
     385              :         /* do draw */
     386            0 :         cairo_move_to( cr, shape_int_rectangle_get_left(label_box), shape_int_rectangle_get_top(label_box) );
     387            0 :         pango_layout_set_text( font_layout, label, GUI_SKETCH_RESULT_LIST_PANGO_AUTO_DETECT_LENGTH );
     388            0 :         const unsigned int text_width
     389            0 :             = shape_int_rectangle_get_width(label_box)
     390            0 :             +(2.0*OBJ_GAP);  /* add gap to avoid line breaks by rounding errors and whitespace character widths */
     391            0 :         pango_layout_set_width(font_layout, text_width * PANGO_SCALE );
     392            0 :         pango_cairo_show_layout( cr, font_layout );
     393              :     }
     394              : 
     395              :     /* draw the icon */
     396              :     {
     397              :         /* what to draw */
     398            0 :         const data_type_t result_type = data_search_result_get_match_type( result );
     399              :         gui_type_resource_t *const type_data
     400            0 :             = gui_type_resource_list_get_type ( &((*this_).selector), result_type );
     401            0 :         GdkTexture *const icon = gui_type_resource_get_icon( type_data );
     402              : 
     403              :         /* where to draw to */
     404              :         const shape_int_rectangle_t *const icon_box
     405            0 :             = pos_search_result_get_icon_box_const( element );
     406            0 :         const int x = shape_int_rectangle_get_left(icon_box);
     407            0 :         const int y = shape_int_rectangle_get_top(icon_box);
     408              :         /* double icon_width = gdk_texture_get_width ( icon ); */
     409              :         /* double icon_height = gdk_texture_get_width ( icon ); */
     410              : 
     411              :         /* do draw */
     412            0 :         gui_sketch_texture_draw( (*this_).texture_downloader, icon, x, y, cr );
     413              :     }
     414              : 
     415            0 :     U8_TRACE_END();
     416            0 : }
     417              : 
     418              : 
     419              : /*
     420              : Copyright 2018-2025 Andreas Warnke
     421              : 
     422              : Licensed under the Apache License, Version 2.0 (the "License");
     423              : you may not use this file except in compliance with the License.
     424              : You may obtain a copy of the License at
     425              : 
     426              :     http://www.apache.org/licenses/LICENSE-2.0
     427              : 
     428              : Unless required by applicable law or agreed to in writing, software
     429              : distributed under the License is distributed on an "AS IS" BASIS,
     430              : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     431              : See the License for the specific language governing permissions and
     432              : limitations under the License.
     433              : */
        

Generated by: LCOV version 2.0-1