Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2004 Richard Wilson <not_ginger_matt@users.sourceforge.net>
  3.  * Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
  4.  *
  5.  * This file is part of NetSurf, http://www.netsurf-browser.org/
  6.  *
  7.  * NetSurf is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; version 2 of the License.
  10.  *
  11.  * NetSurf is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  */
  19.  
  20. /** \file
  21.  * Generic tree handling (implementation).
  22.  */
  23.  
  24. #include <assert.h>
  25. #include <stdbool.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include "content/content.h"
  30. #include "content/hlcache.h"
  31. #include "css/utils.h"
  32. #include "desktop/browser.h"
  33. #include "desktop/knockout.h"
  34. #include "desktop/textarea.h"
  35. #include "desktop/textinput.h"
  36. #include "desktop/tree.h"
  37. #include "desktop/options.h"
  38. #include "desktop/plotters.h"
  39. #include "render/font.h"
  40. #include "utils/log.h"
  41. #include "utils/messages.h"
  42. #include "utils/utils.h"
  43. #include "utils/url.h"
  44.  
  45. #undef TREE_NOISY_DEBUG
  46.  
  47. #define MAXIMUM_URL_LENGTH 1024
  48.  
  49. #define TREE_TEXT_SIZE_PT 11
  50. #define TREE_ICON_SIZE 17
  51. #define NODE_INSTEP 20
  52.  
  53. static int tree_text_size_px;
  54. static int TREE_LINE_HEIGHT;
  55.  
  56. static char *tree_icons_dir = NULL;
  57.  
  58. static plot_font_style_t plot_fstyle = {
  59.         .family = PLOT_FONT_FAMILY_SANS_SERIF,
  60.         .size = TREE_TEXT_SIZE_PT * FONT_SIZE_SCALE,
  61.         .weight = 400,
  62.         .flags = FONTF_NONE
  63. };
  64.  
  65. static plot_font_style_t plot_fstyle_def_folder = {
  66.         .family = PLOT_FONT_FAMILY_SANS_SERIF,
  67.         .size = TREE_TEXT_SIZE_PT * FONT_SIZE_SCALE,
  68.         .weight = 700,
  69.         .flags = FONTF_NONE
  70. };
  71.  
  72. static plot_font_style_t plot_fstyle_selected = {
  73.         .family = PLOT_FONT_FAMILY_SANS_SERIF,
  74.         .size = TREE_TEXT_SIZE_PT * FONT_SIZE_SCALE,
  75.         .weight = 400,
  76.         .flags = FONTF_NONE
  77. };
  78.  
  79. static plot_font_style_t plot_fstyle_selected_def_folder = {
  80.         .family = PLOT_FONT_FAMILY_SANS_SERIF,
  81.         .size = TREE_TEXT_SIZE_PT * FONT_SIZE_SCALE,
  82.         .weight = 700,
  83.         .flags = FONTF_NONE
  84. };
  85.  
  86. /** plot style for treeview backgrounds. */
  87. static plot_style_t plot_style_fill_tree_background = {
  88.         .fill_type = PLOT_OP_TYPE_SOLID
  89. };
  90.  
  91. /** plot style for treeview backgrounds. */
  92. static plot_style_t plot_style_fill_tree_selected = {
  93.         .fill_type = PLOT_OP_TYPE_SOLID
  94. };
  95.  
  96. /** plot style for treeview furniture lines. */
  97. static plot_style_t plot_style_stroke_tree_furniture = {
  98.         .stroke_type = PLOT_OP_TYPE_SOLID
  99. };
  100.  
  101. /** plot style for treeview furniture fills. */
  102. static plot_style_t plot_style_fill_tree_furniture = {
  103.         .fill_type = PLOT_OP_TYPE_SOLID
  104. };
  105.  
  106. struct node;
  107. struct tree;
  108.  
  109. struct node_element_box {
  110.         int x;                          /**< X offset from origin */
  111.         int y;                          /**< Y offset from origin */
  112.         int width;                      /**< Element width */
  113.         int height;                     /**< Element height */
  114. };
  115.  
  116. struct node_element {
  117.         struct node *parent;            /**< Parent node */
  118.         node_element_type type;         /**< Element type */
  119.         struct node_element_box box;    /**< Element bounding box */
  120.         const char *text;               /**< Text for the element */
  121.         void *bitmap;                   /**< Bitmap for the element */
  122.         struct node_element *next;      /**< Next node element */
  123.         unsigned int flag;              /**< Client specified flag for data
  124.                                            being represented */
  125.         bool editable;                  /**< Whether the node text can be
  126.                                          * modified, editable text is deleted
  127.                                          * without noticing the tree user
  128.                                          */
  129. };
  130.  
  131. struct node {
  132.         bool selected;                  /**< Whether the node is selected */
  133.         bool expanded;                  /**< Whether the node is expanded */
  134.         bool folder;                    /**< Whether the node is a folder */
  135.         bool def_folder;                /**< Whether the node is the default folder */
  136.         bool retain_in_memory;          /**< Whether the node remains
  137.                                            in memory after deletion */
  138.         bool deleted;                   /**< Whether the node is currently
  139.                                            deleted */
  140.         bool processing;                /**< Internal flag used when moving */
  141.         struct node_element_box box;    /**< Bounding box of all elements */
  142.         struct node_element data;       /**< Data to display */
  143.         struct node *parent;            /**< Parent entry (NULL for root) */
  144.         struct node *child;             /**< First child */
  145.         struct node *last_child;        /**< Last child */
  146.         struct node *previous;          /**< Previous child of the parent */
  147.         struct node *next;              /**< Next child of the parent */
  148.  
  149.         /** Sorting function for        the node (for folder nodes only) */
  150.         int (*sort) (struct node *, struct node *);
  151.         /** Gets called for each deleted node_element and on node launch */
  152.         tree_node_user_callback user_callback;
  153.         /** User data to be passed to delete_callback */
  154.         void *callback_data;
  155. };
  156.  
  157. struct tree {
  158.         struct node *root;              /* Tree root element */
  159.         int width;                      /* Tree width */
  160.         int height;                     /* Tree height */
  161.         unsigned int flags;             /* Tree flags */
  162.         struct textarea *textarea;      /* Handle for UTF-8 textarea */
  163.         int ta_height;                  /* Textarea height */
  164.         struct node_element *editing;   /* Node element being edited */
  165.  
  166.         bool redraw;                    /* Flag indicating whether the tree
  167.                                            should be redrawn on layout
  168.                                            changes */
  169.         tree_drag_type drag;
  170.         const struct treeview_table *callbacks;
  171.         void *client_data;              /* User assigned data for the
  172.                                            callbacks */
  173.         struct node *def_folder;        /* Node to be used for additions by default */
  174. };
  175.  
  176. void tree_set_icon_dir(char *icon_dir)
  177. {
  178.         LOG(("Tree icon directory set to %s", icon_dir));
  179.         tree_icons_dir = icon_dir;
  180. }
  181.  
  182. /**
  183.  * Set up colours for plot styles used in tree redraw.
  184.  */
  185. void tree_setup_colours(void)
  186. {
  187.         /* Background colour */
  188.         plot_style_fill_tree_background.fill_colour =
  189.                         gui_system_colour_char("Window");
  190.  
  191.         /* Selection background colour */
  192.         plot_style_fill_tree_selected.fill_colour =
  193.                         gui_system_colour_char("Highlight");
  194.  
  195.         /* Furniture line colour */
  196.         plot_style_stroke_tree_furniture.stroke_colour = blend_colour(
  197.                         gui_system_colour_char("Window"),
  198.                         gui_system_colour_char("WindowText"));
  199.  
  200.         /* Furniture fill colour */
  201.         plot_style_fill_tree_furniture.fill_colour =
  202.                         gui_system_colour_char("Window");
  203.  
  204.         /* Text colour */
  205.         plot_fstyle.foreground = gui_system_colour_char("WindowText");
  206.         plot_fstyle.background = gui_system_colour_char("Window");
  207.         plot_fstyle_def_folder.foreground =
  208.                         gui_system_colour_char("InfoText");
  209.         plot_fstyle_def_folder.background =
  210.                         gui_system_colour_char("Window");
  211.  
  212.         /* Selected text colour */
  213.         plot_fstyle_selected.foreground =
  214.                         gui_system_colour_char("HighlightText");
  215.         plot_fstyle_selected.background =
  216.                         gui_system_colour_char("Highlight");
  217.         plot_fstyle_selected_def_folder.foreground =
  218.                         gui_system_colour_char("HighlightText");
  219.         plot_fstyle_selected_def_folder.background =
  220.                         gui_system_colour_char("Highlight");
  221. }
  222.  
  223.  
  224. /**
  225.  * Creates and initialises a new tree.
  226.  *
  227.  * \param flags         Flag word for flags to create the new tree with
  228.  * \param callbacks     Callback functions to support the tree in the frontend.
  229.  * \param client_data   Data to be passed to start_redraw and end_redraw
  230.  * \return              The newly created tree, or NULL on memory exhaustion
  231.  */
  232. struct tree *tree_create(unsigned int flags,
  233.                 const struct treeview_table *callbacks, void *client_data)
  234. {
  235.         struct tree *tree;
  236.         char *title;
  237.  
  238.         tree = calloc(sizeof(struct tree), 1);
  239.         if (tree == NULL) {
  240.                 LOG(("calloc failed"));
  241.                 warn_user("NoMemory", 0);
  242.                 return NULL;
  243.         }
  244.  
  245.         title = strdup("Root");
  246.         if (title == NULL) {
  247.                 LOG(("malloc failed"));
  248.                 warn_user("NoMemory", 0);
  249.                 free(tree);
  250.                 return NULL;
  251.         }
  252.         tree->root = tree_create_folder_node(NULL, NULL, title,
  253.                                              false, false, false);
  254.         if (tree->root == NULL) {
  255.                 free(title);
  256.                 free(tree);
  257.                 return NULL;
  258.         }
  259.         tree->root->expanded = true;
  260.  
  261.         tree->width = 0;
  262.         tree->height = 0;
  263.         tree->flags = flags;
  264.         tree->textarea = NULL;
  265.         tree->editing = NULL;
  266.         tree->redraw = false;
  267.         tree->drag = TREE_NO_DRAG;
  268.         tree->callbacks = callbacks;
  269.         tree->client_data = client_data;
  270.  
  271.         /* Set text height in pixels */
  272.         tree_text_size_px =
  273.                         (TREE_TEXT_SIZE_PT * FIXTOINT(nscss_screen_dpi) + 36) /
  274.                         72;
  275.         /* Set line height appropriate for this text height in pixels
  276.          * Using 4/3 text height */
  277.         TREE_LINE_HEIGHT = (tree_text_size_px * 8 + 3) / 6;
  278.  
  279.         /* But if that's too small for the icons, base the line height on
  280.          * the icon height. */
  281.         if (TREE_LINE_HEIGHT < TREE_ICON_SIZE + 2)
  282.                 TREE_LINE_HEIGHT = TREE_ICON_SIZE + 2;
  283.  
  284.         tree_setup_colours();
  285.  
  286.         return tree;
  287. }
  288.  
  289.  
  290. /**
  291.  * Recalculates the dimensions of a node element.
  292.  *
  293.  * \param tree     the tree to which the element belongs, may be NULL
  294.  * \param element  the element to recalculate
  295.  */
  296. static void tree_recalculate_node_element(struct tree *tree,
  297.                 struct node_element *element)
  298. {
  299.         struct bitmap *bitmap = NULL;
  300.         int width, height;
  301.         static char *cache_text = NULL;
  302.         static int cache_size = 0;
  303.         plot_font_style_t *fstyle;
  304.         static plot_font_style_t *cache_fstyle = NULL;
  305.  
  306.         assert(element != NULL);
  307.  
  308.         if (element->parent->def_folder)
  309.                 fstyle = &plot_fstyle_def_folder;
  310.         else
  311.                 fstyle = &plot_fstyle;
  312.  
  313.         switch (element->type) {
  314.         case NODE_ELEMENT_TEXT_PLUS_ICON:
  315.         case NODE_ELEMENT_TEXT:
  316.                 if(element->text == NULL)
  317.                         break;
  318.  
  319.                 if (tree != NULL && element == tree->editing) {
  320.                         textarea_get_dimensions(tree->textarea,
  321.                                                 &element->box.width, NULL);
  322.                 } else {
  323.                         if ((cache_text != NULL) &&
  324.                                 (strcmp(cache_text, element->text) == 0) &&
  325.                                 (cache_fstyle == fstyle)) {
  326.                                 element->box.width = cache_size;
  327.                                 #ifdef TREE_NOISY_DEBUG
  328.                                         LOG(("Tree font width cache hit"));
  329.                                 #endif
  330.                         } else {
  331.                                 if(cache_text != NULL) free(cache_text);
  332.                                 nsfont.font_width(fstyle,
  333.                                                   element->text,
  334.                                                   strlen(element->text),
  335.                                                   &cache_size);
  336.                                 element->box.width = cache_size;
  337.                                 cache_text = strdup(element->text);
  338.                                 cache_fstyle = fstyle;
  339.                         }
  340.                 }
  341.  
  342.                 element->box.width += 8;
  343.                 element->box.height = TREE_LINE_HEIGHT;
  344.  
  345.                 if (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)
  346.                         element->box.width += NODE_INSTEP;
  347.  
  348.                 break;
  349.  
  350.         case NODE_ELEMENT_BITMAP:
  351.                 bitmap = element->bitmap;
  352.                 if (bitmap != NULL) {
  353.                         width = bitmap_get_width(bitmap);
  354.                         height = bitmap_get_height(bitmap);
  355.                         element->box.width = width + 1;
  356.                         element->box.height = height + 2;
  357.                 } else {
  358.                         element->box.width = 0;
  359.                         element->box.height = 0;
  360.                 }
  361.                 break;
  362.         }
  363. }
  364.  
  365.  
  366. /**
  367.  * Calculates the height of a node including any children
  368.  *
  369.  * \param node  the node to calculate the height of
  370.  * \return the total height of the node and children
  371.  */
  372. static int tree_get_node_height(struct node *node)
  373. {
  374.         int y1;
  375.  
  376.         assert(node != NULL);
  377.  
  378.         if ((node->child == NULL) || (node->expanded == false)) {
  379.                 return node->box.height;
  380.         }
  381.  
  382.         y1 = node->box.y;
  383.         if (y1 < 0) {
  384.                 y1 = 0;
  385.         }
  386.         node = node->child;
  387.  
  388.         while ((node->next != NULL) ||
  389.                ((node->child != NULL) && (node->expanded))) {
  390.                 for (; node->next != NULL; node = node->next);
  391.  
  392.                 if ((node->child != NULL) && (node->expanded)) {
  393.                         node = node->child;
  394.                 }
  395.         }
  396.         return node->box.y + node->box.height - y1;
  397. }
  398.  
  399.  
  400. /**
  401.  * Calculates the width of a node including any children
  402.  *
  403.  * \param node  the node to calculate the height of
  404.  * \return the total width of the node and children
  405.  */
  406. static int tree_get_node_width(struct node *node)
  407. {
  408.         int width = 0;
  409.         int child_width;
  410.  
  411.         assert(node != NULL);
  412.  
  413.         for (; node != NULL; node = node->next) {
  414.                 if (width < (node->box.x + node->box.width)) {
  415.                         width = node->box.x + node->box.width;
  416.                 }
  417.  
  418.                 if ((node->child != NULL) && (node->expanded)) {
  419.                         child_width = tree_get_node_width(node->child);
  420.                         if (width < child_width) {
  421.                                 width = child_width;
  422.                         }
  423.                 }
  424.         }
  425.         return width;
  426. }
  427.  
  428.  
  429. /**
  430.  * Recalculates the position of a node, its siblings and children.
  431.  *
  432.  * \param tree  the tree to which 'root' belongs
  433.  * \param root  the root node to update from
  434.  */
  435. static void tree_recalculate_node_positions(struct tree *tree,
  436.                 struct node *root)
  437. {
  438.         struct node *parent;
  439.         struct node *node;
  440.         struct node *child;
  441.         struct node_element *element;
  442.         int y;
  443.         bool has_icon;
  444.  
  445.         for (node = root; node != NULL; node = node->next) {
  446.  
  447.                 parent = node->parent;
  448.  
  449.                 if (node->previous != NULL) {
  450.                         node->box.x = node->previous->box.x;
  451.                         node->box.y = node->previous->box.y +
  452.                                 tree_get_node_height(node->previous);
  453.                 } else if (parent != NULL) {
  454.                         node->box.x = parent->box.x + NODE_INSTEP;
  455.                         node->box.y = parent->box.y +
  456.                                 parent->box.height;
  457.                         for (child = parent->child; child != node;
  458.                              child = child->next)
  459.                                 node->box.y += child->box.height;
  460.                 } else {
  461.                         node->box.x = tree->flags & TREE_NO_FURNITURE
  462.                                 ? -NODE_INSTEP + 4 : 0;
  463.                         node->box.y = -TREE_LINE_HEIGHT;
  464.                 }
  465.  
  466.                 if (!node->expanded) {
  467.                         node->data.box.x = node->box.x;
  468.                         node->data.box.y = node->box.y;
  469.                         continue;
  470.                 }
  471.  
  472.                 if (node->folder) {
  473.                         node->data.box.x = node->box.x;
  474.                         node->data.box.y = node->box.y;
  475.                         tree_recalculate_node_positions(tree, node->child);
  476.                 } else {
  477.                         y = node->box.y;
  478.                         has_icon = false;
  479.                         for (element = &node->data; element != NULL;
  480.                              element = element->next)
  481.                                 if (element->type ==
  482.                                     NODE_ELEMENT_TEXT_PLUS_ICON) {
  483.                                         has_icon = true;
  484.                                         break;
  485.                                 }
  486.  
  487.                         for (element = &node->data; element != NULL;
  488.                              element = element->next) {
  489.                                 element->box.x = node->box.x;
  490.                                 if (element->type !=
  491.                                     NODE_ELEMENT_TEXT_PLUS_ICON &&
  492.                                     has_icon)
  493.                                         element->box.x += NODE_INSTEP;
  494.                                 element->box.y = y;
  495.                                 y += element->box.height;
  496.                         }
  497.                 }
  498.  
  499.         }
  500. }
  501.  
  502.  
  503. /**
  504.  * Recalculates the size of a node.
  505.  *
  506.  * \param tree                  the tree to which node belongs, may be NULL
  507.  * \param node                  the node to update
  508.  * \param recalculate_sizes     whether the node elements have changed
  509.  */
  510. static void tree_recalculate_node_sizes(struct tree *tree, struct node *node,
  511.                 bool recalculate_sizes)
  512. {
  513.         struct node_element *element;
  514.         int height;
  515.  
  516.         assert(node != NULL);
  517.  
  518.         height = node->box.height;
  519.         node->box.width = 0;
  520.         node->box.height = 0;
  521.         if (node->expanded) {
  522.                 for (element = &node->data; element != NULL;
  523.                      element = element->next) {
  524.                         if (recalculate_sizes) {
  525.                                 #ifdef TREE_NOISY_DEBUG
  526.                                         if(element->text) LOG(("%s", element->text));
  527.                                 #endif
  528.                                 tree_recalculate_node_element(tree, element);
  529.                         }
  530.                         node->box.width = (node->box.width > element->box.x +
  531.                                            element->box.width - node->box.x) ?
  532.                                 node->box.width :
  533.                                 element->box.width + element->box.x -
  534.                                 node->box.x;
  535.                         node->box.height += element->box.height;
  536.                 }
  537.         } else {
  538.                 if (recalculate_sizes)
  539.                         for (element = &node->data; element != NULL;
  540.                              element = element->next) {
  541.                                 #ifdef TREE_NOISY_DEBUG
  542.                                         if(element->text) LOG(("%s", element->text));
  543.                                 #endif
  544.                                 tree_recalculate_node_element(tree, element);
  545.                         }
  546.  
  547.                 node->box.width = node->data.box.width;
  548.                 node->box.height = node->data.box.height;
  549.         }
  550.  
  551.         if (tree != NULL && height != node->box.height)
  552.                 tree_recalculate_node_positions(tree, tree->root);
  553. }
  554.  
  555.  
  556. /**
  557.  * Creates a folder node with the specified title, and optionally links it into
  558.  * the tree.
  559.  *
  560.  * \param tree              the owner tree of 'parent', may be NULL
  561.  * \param parent            the parent node, or NULL not to link
  562.  * \param title             the node title (not copied, used directly)
  563.  * \param editable          if true, the node title will be editable
  564.  * \param retain_in_memory  if true, the node will stay in memory after deletion
  565.  * \param deleted           if true, the node is created with the deleted flag
  566.  * \return                  the newly created node.
  567.  */
  568. struct node *tree_create_folder_node(struct tree *tree, struct node *parent,
  569.                 const char *title, bool editable, bool retain_in_memory,
  570.                 bool deleted)
  571. {
  572.         struct node *node;
  573.  
  574.         assert(title != NULL);
  575.  
  576.         node = calloc(sizeof(struct node), 1);
  577.         if (node == NULL) {
  578.                 LOG(("calloc failed"));
  579.                 warn_user("NoMemory", 0);
  580.                 return NULL;
  581.         }
  582.         node->folder = true;
  583.         node->retain_in_memory = retain_in_memory;
  584.         node->deleted = deleted;
  585.         node->data.parent = node;
  586.         node->data.type = NODE_ELEMENT_TEXT;
  587.         node->data.text = title;
  588.         node->data.flag = TREE_ELEMENT_TITLE;
  589.         node->data.editable = editable;
  590.         node->sort = NULL;
  591.         node->user_callback = NULL;
  592.         node->previous = NULL;
  593.  
  594.         tree_recalculate_node_sizes(tree, node, true);
  595.         if (parent != NULL)
  596.                 tree_link_node(tree, parent, node, false);
  597.  
  598.         return node;
  599. }
  600.  
  601.  
  602. /**
  603.  * Creates a leaf node with the specified title, and optionally links it into
  604.  * the tree.
  605.  *
  606.  * \param tree              the owner tree of 'parent', may be NULL
  607.  * \param parent            the parent node, or NULL not to link
  608.  * \param title             the node title (not copied, used directly)
  609.  * \param editable          if true, the node title will be editable
  610.  * \param retain_in_memory  if true, the node will stay in memory after deletion
  611.  * \param deleted           if true, the node is created with the deleted flag
  612.  * \return                  the newly created node.
  613.  */
  614. struct node *tree_create_leaf_node(struct tree *tree, struct node *parent,
  615.                 const char *title, bool editable, bool retain_in_memory,
  616.                 bool deleted)
  617. {
  618.         struct node *node;
  619.  
  620.         assert(title != NULL);
  621.  
  622.         node = calloc(sizeof(struct node), 1);
  623.         if (node == NULL) {
  624.                 LOG(("calloc failed"));
  625.                 warn_user("NoMemory", 0);
  626.                 return NULL;
  627.         }
  628.  
  629.         node->folder = false;
  630.         node->retain_in_memory = retain_in_memory;
  631.         node->deleted = deleted;
  632.         node->data.parent = node;
  633.         node->data.type = NODE_ELEMENT_TEXT;
  634.         node->data.text = title;
  635.         node->data.flag = TREE_ELEMENT_TITLE;
  636.         node->data.editable = editable;
  637.         node->sort = NULL;
  638.         node->user_callback = NULL;
  639.         node->previous = NULL;
  640.  
  641.         tree_recalculate_node_sizes(tree, node, true);
  642.         if (parent != NULL)
  643.                 tree_link_node(tree, parent, node, false);
  644.  
  645.         return node;
  646. }
  647.  
  648.  
  649. /**
  650.  * Creates an empty text node element and links it to a node.
  651.  *
  652.  * \param parent  the parent node
  653.  * \param type    the required element type
  654.  * \param flag    user assigned flag used for searches
  655.  * \return        the newly created element.
  656.  */
  657. struct node_element *tree_create_node_element(struct node *parent,
  658.                 node_element_type type, unsigned int flag, bool editable)
  659. {
  660.         struct node_element *element;
  661.  
  662.         element = calloc(sizeof(struct node_element), 1);
  663.         if (element == NULL)
  664.                 return NULL;
  665.  
  666.         element->parent = parent;
  667.         element->flag = flag;
  668.         element->type = type;
  669.         element->editable = editable;
  670.         element->next = parent->data.next;
  671.         parent->data.next = element;
  672.  
  673.         return element;
  674. }
  675.  
  676.  
  677. /**
  678.  * Inserts a node into the correct place according to the parent's sort function
  679.  *
  680.  * \param parent  the node whose child node 'node' becomes
  681.  * \param node    the node to be inserted
  682.  */
  683. static void tree_sort_insert(struct node *parent, struct node *node)
  684. {
  685.         struct node *after;
  686.  
  687.         assert(node != NULL);
  688.         assert(parent != NULL);
  689.         assert(parent->sort != NULL);
  690.  
  691.         after = parent->last_child;
  692.         while ((after != NULL) &&
  693.                (parent->sort(node, after) == -1))
  694.                 after = after->previous;
  695.  
  696.         if (after != NULL) {
  697.                 if (after->next != NULL)
  698.                         after->next->previous = node;
  699.                 node->next = after->next;
  700.                 node->previous = after;
  701.                 after->next = node;
  702.         } else {
  703.                 node->previous = NULL;
  704.                 node->next = parent->child;
  705.                 if (parent->child != NULL) {
  706.                         parent->child->previous = node;
  707.                 }
  708.                 parent->child = node;
  709.         }
  710.  
  711.         if (node->next == NULL)
  712.                 parent->last_child = node;
  713.  
  714.         node->parent = parent;
  715. }
  716.  
  717.  
  718. /**
  719.  * Recalculates the size of a tree.
  720.  *
  721.  * \param tree  the tree to recalculate
  722.  */
  723. static void tree_recalculate_size(struct tree *tree)
  724. {
  725.         int width, height;
  726.  
  727.         assert(tree != NULL);
  728.  
  729.         width = tree->width;
  730.         height = tree->height;
  731.  
  732.         tree->width = tree_get_node_width(tree->root);
  733.         tree->height = tree_get_node_height(tree->root);
  734.  
  735.         if ((width != tree->width) || (height != tree->height))
  736.                 tree->callbacks->resized(tree, tree->width, tree->height,
  737.                                          tree->client_data);
  738. }
  739.  
  740. /**
  741.  * Recalculate the node data and redraw the relevant section of the tree.
  742.  *
  743.  * \param tree               the tree to redraw, may be NULL
  744.  * \param node               the node to update
  745.  * \param recalculate_sizes  whether the elements have changed
  746.  * \param expansion          the request is the result of a node expansion
  747.  */
  748. static void tree_handle_node_changed(struct tree *tree, struct node *node,
  749.                 bool recalculate_sizes, bool expansion)
  750. {
  751.         int node_width, node_height, tree_width, tree_height;
  752.  
  753.         assert(node != NULL);
  754.         assert(tree != NULL);
  755.  
  756.         node_width = node->box.width;
  757.         node_height = node->box.height;
  758.         tree_width = tree->width;
  759.         tree_height = tree->height;
  760.  
  761.         if ((recalculate_sizes) || (expansion)) {
  762.                 tree_recalculate_node_sizes(tree, node, true);
  763.         }
  764.  
  765.         if (tree != NULL) {
  766.                 if ((node->box.height != node_height) || (expansion)) {
  767.                         tree_recalculate_node_positions(tree, tree->root);
  768.                         tree_recalculate_size(tree);
  769.                         if (tree->width > tree_width)
  770.                                 tree_width = tree->width;
  771.                         if (tree->height > tree_height)
  772.                                 tree_height = tree->height;
  773.                         if (tree->redraw) {
  774.                                 tree->callbacks->redraw_request(0, node->box.y,
  775.                                                 tree_width,
  776.                                                 tree_height - node->box.y,
  777.                                                 tree->client_data);
  778.                         }
  779.                 } else {
  780.                         if (node->box.width > node_width)
  781.                                 node_width = node->box.width;
  782.                         if (tree->redraw)
  783.                                 tree->callbacks->redraw_request(node->box.x,
  784.                                                 node->box.y,
  785.                                                 node_width, node->box.height,
  786.                                                 tree->client_data);
  787.                         if (recalculate_sizes) {
  788.                                 tree_recalculate_size(tree);
  789.                         }
  790.                 }
  791.         }
  792. }
  793.  
  794.  
  795. /**
  796.  * Links a node to another node.
  797.  *
  798.  * \param tree    the tree in which the link takes place, may be NULL
  799.  * \param link    the node to link before/as a child (folders)
  800.  *                or before/after (link)
  801.  * \param node    the node to link
  802.  * \param before  whether to link siblings before or after the supplied node
  803.  */
  804. void tree_link_node(struct tree *tree, struct node *link, struct node *node,
  805.                 bool before)
  806. {
  807.  
  808.         struct node *parent;
  809.         bool sort = false;
  810.  
  811.         assert(link != NULL);
  812.         assert(node != NULL);
  813.  
  814.         if ((link->folder == 0) || (before)) {
  815.                 parent = node->parent = link->parent;
  816.                 if (parent->sort) {
  817.                         sort = true;
  818.                 } else {
  819.                         if (before) {
  820.                                 node->next = link;
  821.                                 node->previous = link->previous;
  822.                                 if (link->previous != NULL)
  823.                                         link->previous->next = node;
  824.                                 link->previous = node;
  825.                                 if ((parent != NULL) && (parent->child == link))
  826.                                         parent->child = node;
  827.                         } else {
  828.                                 node->previous = link;
  829.                                 node->next = link->next;
  830.                                 if (link->next != NULL)
  831.                                         link->next->previous = node;
  832.                                 link->next = node;
  833.                                 if ((parent != NULL) &&
  834.                                     (parent->last_child == link))
  835.                                         parent->last_child = node;
  836.                         }
  837.                 }
  838.         } else {
  839.                 parent = node->parent = link;
  840.                 if (parent->sort != NULL) {
  841.                         sort = true;
  842.                 } else {
  843.                         node->next = NULL;
  844.                         if (link->child == NULL) {
  845.                                 link->child = link->last_child = node;
  846.                                 node->previous = NULL;
  847.                         } else {
  848.                                 link->last_child->next = node;
  849.                                 node->previous = link->last_child;
  850.                                 link->last_child = node;
  851.                         }
  852.                 }
  853.  
  854.         }
  855.  
  856.         if (sort) {
  857.                 tree_sort_insert(parent, node);
  858.         }
  859.  
  860.         tree_handle_node_changed(tree, link, false, true);
  861.  
  862.         node->deleted = false;
  863. }
  864.  
  865.  
  866. /**
  867.  * Recalculate the node element and redraw the relevant section of the tree.
  868.  * The tree size is not updated.
  869.  *
  870.  * \param tree     the tree to redraw, may be NULL
  871.  * \param element  the node element to update
  872.  */
  873. static void tree_handle_node_element_changed(struct tree *tree,
  874.                 struct node_element *element, bool text_changed)
  875. {
  876.         int width, height;
  877.  
  878.         assert(element != NULL);
  879.  
  880.         width = element->box.width;
  881.         height = element->box.height;
  882.  
  883.         if(text_changed == true) {
  884.                 #ifdef TREE_NOISY_DEBUG
  885.                         if(element->text) LOG(("%s", element->text));
  886.                 #endif
  887.                 tree_recalculate_node_element(tree, element);
  888.         }
  889.  
  890.         if (element->box.height != height) {
  891.                 tree_recalculate_node_sizes(tree, element->parent, false);
  892.                 if ((tree != NULL) && (tree->redraw)) {
  893.                         tree->callbacks->redraw_request(0, element->box.y,
  894.                                         tree->width + element->box.width -
  895.                                         width,
  896.                                         tree->height - element->box.y +
  897.                                         element->box.height - height,
  898.                                         tree->client_data);
  899.                 }
  900.         } else {
  901.                 if (element->box.width != width) {
  902.                         tree_recalculate_node_sizes(tree, element->parent,
  903.                                                     false);
  904.                 }
  905.  
  906.                 if (tree != NULL) {
  907.                         width = (width > element->box.width) ? width :
  908.                                 element->box.width;
  909.                         if (tree->redraw) {
  910.                                 tree->callbacks->redraw_request(element->box.x,
  911.                                                 element->box.y,
  912.                                                 width,
  913.                                                 element->box.height,
  914.                                                 tree->client_data);
  915.                         }
  916.                 }
  917.         }
  918. }
  919.  
  920.  
  921. /**
  922.  * Stops editing a node_element
  923.  *
  924.  * \param tree          The tree to stop editing for
  925.  * \param keep_changes  If true the changes made to the text will be kept,
  926.  *                      if false they will be dropped
  927.  */
  928. static void tree_stop_edit(struct tree *tree, bool keep_changes)
  929. {
  930.         int text_len;
  931.         char *text = NULL;
  932.         struct node_element *element;
  933.         struct node_msg_data msg_data;
  934.         node_callback_resp response;
  935.  
  936.         assert(tree != NULL);
  937.  
  938.         if (tree->editing == NULL || tree->textarea == NULL)
  939.                 return;
  940.  
  941.         element = tree->editing;
  942.  
  943.         if (keep_changes) {
  944.                 text_len = textarea_get_text(tree->textarea, NULL, 0);
  945.                 text = malloc(text_len * sizeof(char));
  946.                 if (text == NULL) {
  947.                         LOG(("malloc failed"));
  948.                         warn_user("NoMemory", 0);
  949.                         textarea_destroy(tree->textarea);
  950.                         tree->textarea = NULL;
  951.                         return;
  952.                 }
  953.                 textarea_get_text(tree->textarea, text, text_len);
  954.         }
  955.  
  956.  
  957.         if (keep_changes && element->parent->user_callback != NULL) {
  958.                 msg_data.msg = NODE_ELEMENT_EDIT_FINISHING;
  959.                 msg_data.flag = element->flag;
  960.                 msg_data.node = element->parent;
  961.                 msg_data.data.text = text;
  962.                 response = element->parent->user_callback(
  963.                         element->parent->callback_data,
  964.                         &msg_data);
  965.  
  966.                 switch (response) {
  967.                 case NODE_CALLBACK_REJECT:
  968.                         free(text);
  969.                         text = NULL;
  970.                         break;
  971.                 case NODE_CALLBACK_CONTINUE:
  972.                         free(text);
  973.                         text = NULL;
  974.                         return;
  975.                 case NODE_CALLBACK_HANDLED:
  976.                 case NODE_CALLBACK_NOT_HANDLED:
  977.                         text = msg_data.data.text;
  978.                         break;
  979.                 }
  980.         }
  981.  
  982.         textarea_destroy(tree->textarea);
  983.         tree->textarea = NULL;
  984.         tree->editing = NULL;
  985.  
  986.         if (text != NULL)
  987.                 tree_update_node_element(tree, element, text, NULL);
  988.         else
  989.                 tree_handle_node_element_changed(tree, element, true);
  990.  
  991.  
  992.         tree_recalculate_size(tree);
  993.         if (element->parent->user_callback != NULL) {
  994.                 msg_data.msg = keep_changes ? NODE_ELEMENT_EDIT_FINISHED :
  995.                                 NODE_ELEMENT_EDIT_CANCELLED;
  996.                 msg_data.flag = element->flag;
  997.                 msg_data.node = element->parent;
  998.                 element->parent->user_callback(element->parent->callback_data,
  999.                                                &msg_data);
  1000.         }
  1001. }
  1002.  
  1003.  
  1004. /**
  1005.  * Delinks a node from the tree structures.
  1006.  *
  1007.  * \param tree  the tree in which the delink takes place, may be NULL
  1008.  * \param node  the node to delink
  1009.  */
  1010. void tree_delink_node(struct tree *tree, struct node *node)
  1011. {
  1012.         struct node *parent;
  1013.  
  1014.         assert(node != NULL);
  1015.  
  1016.         /* do not remove the root */
  1017.         if (tree != NULL && node == tree->root)
  1018.                 return;
  1019.         if ((tree != NULL) && (tree->editing != NULL)) {
  1020.                 parent = tree->editing->parent;
  1021.                 while (parent != NULL) {
  1022.                         if (node == parent) {
  1023.                                 tree_stop_edit(tree, false);
  1024.                                 break;
  1025.                         }
  1026.                         parent = parent->parent;
  1027.                 }
  1028.         }
  1029.  
  1030.         if (node->parent->child == node)
  1031.                 node->parent->child = node->next;
  1032.         if (node->parent->last_child == node)
  1033.                 node->parent->last_child = node->previous;
  1034.         parent = node->parent;
  1035.         node->parent = NULL;
  1036.  
  1037.         if (node->previous != NULL)
  1038.                 node->previous->next = node->next;
  1039.         if (node->next != NULL)
  1040.                 node->next->previous = node->previous;
  1041.         node->previous = NULL;
  1042.         node->next = NULL;
  1043.  
  1044.         tree_handle_node_changed(tree, parent, false, true);
  1045. }
  1046.  
  1047.  
  1048. /**
  1049.  * Deletes a node from the tree.
  1050.  *
  1051.  * \param tree      the tree to delete from, may be NULL
  1052.  * \param node      the node to delete
  1053.  * \param siblings  whether to delete all siblings
  1054.  */
  1055. static void tree_delete_node_internal(struct tree *tree, struct node *node,
  1056.                 bool siblings)
  1057. {
  1058.         struct node *next, *child, *parent;
  1059.         struct node_element *e, *f;
  1060.         node_callback_resp response;
  1061.         struct node_msg_data msg_data;
  1062.  
  1063.         assert(node != NULL);
  1064.  
  1065.         if (tree != NULL && tree->root == node)
  1066.                 return;
  1067.  
  1068.         next = node->next;
  1069.         parent = node->parent;
  1070.         if (tree != NULL && parent == tree->root)
  1071.                 parent = NULL;
  1072.         if ((tree != NULL) && (tree->def_folder == node))
  1073.                 tree->def_folder = NULL;
  1074.         tree_delink_node(tree, node);
  1075.         child = node->child;
  1076.         node->child = NULL;
  1077.  
  1078.         node->deleted = true;
  1079.         if (child != NULL)
  1080.                 tree_delete_node_internal(tree, child, true);
  1081.  
  1082.         if (!node->retain_in_memory) {
  1083.                 node->retain_in_memory = true;
  1084.                 for (e = &node->data; e != NULL; e = f) {
  1085.                         if (e->text != NULL) {
  1086.                                 response = NODE_CALLBACK_NOT_HANDLED;
  1087.                                 if (!e->editable &&
  1088.                                     node->user_callback != NULL) {
  1089.                                         msg_data.msg = NODE_DELETE_ELEMENT_TXT;
  1090.                                         msg_data.flag = e->flag;
  1091.                                         msg_data.node = node;
  1092.                                         msg_data.data.text = (void *)e->text;
  1093.                                         response = node->user_callback(
  1094.                                                 node->callback_data,
  1095.                                                 &msg_data);
  1096.                                 }
  1097.                                 if (response != NODE_CALLBACK_HANDLED)
  1098.                                         free((void *)e->text);
  1099.                                 e->text = NULL;
  1100.                         }
  1101.                         if (e->bitmap != NULL) {
  1102.                                 response = NODE_CALLBACK_NOT_HANDLED;
  1103.                                 if (node->user_callback != NULL) {
  1104.                                         msg_data.msg = NODE_DELETE_ELEMENT_IMG;
  1105.                                         msg_data.flag = e->flag;
  1106.                                         msg_data.node = node;
  1107.                                         msg_data.data.bitmap =
  1108.                                                 (void *)e->bitmap;
  1109.                                         response = node->user_callback(
  1110.                                                 node->callback_data,
  1111.                                                 &msg_data);
  1112.                                 }
  1113.                                 /* TODO the type of this field is platform
  1114.                                    dependent */
  1115.                                 if (response != NODE_CALLBACK_HANDLED)
  1116.                                         free(e->bitmap);
  1117.                                 e->bitmap = NULL;
  1118.                         }
  1119.                         f = e->next;
  1120.                         if (e != &node->data)
  1121.                                 free(e);
  1122.                 }
  1123.                 free(node);
  1124.         }
  1125.  
  1126.         if (siblings && next)
  1127.                 tree_delete_node_internal(tree, next, true);
  1128.         if ((tree->flags & TREE_DELETE_EMPTY_DIRS) && parent != NULL &&
  1129.             parent->child == NULL && !parent->deleted)
  1130.                 tree_delete_node_internal(tree, parent, false);
  1131. }
  1132.  
  1133.  
  1134. /**
  1135.  * Deletes all nodes of a tree and the tree itself.
  1136.  *
  1137.  * \param tree the tree to be deleted
  1138.  */
  1139. void tree_delete(struct tree *tree)
  1140. {
  1141.         tree->redraw = false;
  1142.  
  1143.         if (tree->root->child != NULL)
  1144.                 tree_delete_node_internal(tree, tree->root->child, true);
  1145.  
  1146.         free((void *)tree->root->data.text);
  1147.         free(tree->root);
  1148.         free(tree);
  1149. }
  1150.  
  1151.  
  1152. /**
  1153.  * Gets the redraw property of the given tree.
  1154.  *
  1155.  * \param tree  the tree for which to retrieve the property
  1156.  * \return      the redraw property of the tree
  1157.  */
  1158. bool tree_get_redraw(struct tree *tree)
  1159. {
  1160.         return tree->redraw;
  1161. }
  1162.  
  1163.  
  1164. /**
  1165.  * Deletes a node from the tree.
  1166.  *
  1167.  * \param tree      the tree to delete from, may be NULL
  1168.  * \param node      the node to delete
  1169.  * \param siblings  whether to delete all siblings
  1170.  */
  1171. void tree_delete_node(struct tree *tree, struct node *node, bool siblings)
  1172. {
  1173.         int y = node->box.y;
  1174.         int height = tree->height;
  1175.         int width = tree->width;
  1176.         bool redraw_setting = tree->redraw;
  1177.  
  1178.         tree->redraw = false;
  1179.  
  1180.         tree_delete_node_internal(tree, node, siblings);
  1181.         tree_recalculate_node_positions(tree, tree->root);
  1182.  
  1183.         tree->redraw = redraw_setting;
  1184.  
  1185.         if (tree->redraw)
  1186.                 tree->callbacks->redraw_request(0, y,
  1187.                                 width, height, tree->client_data);
  1188.         tree_recalculate_size(tree);
  1189. }
  1190.  
  1191.  
  1192. /**
  1193.  * Sets an icon for a node
  1194.  *
  1195.  * \param tree          The tree to which node belongs, may be NULL
  1196.  * \param node          The node for which the icon is set
  1197.  * \param icon          the image to use
  1198.  */
  1199. void tree_set_node_icon(struct tree *tree, struct node *node,
  1200.                 hlcache_handle *icon)
  1201. {
  1202.         node->data.type = NODE_ELEMENT_TEXT_PLUS_ICON;
  1203.         tree_update_node_element(tree, &(node->data), NULL, icon);
  1204. }
  1205.  
  1206.  
  1207. /**
  1208.  * Updates all siblings and descendants of a node to an expansion state.
  1209.  * No update is performed for the tree changes.
  1210.  *
  1211.  * \param tree          the tree to which 'node' belongs
  1212.  * \param node          the node to set all siblings and descendants of
  1213.  * \param expanded      the expansion state to set
  1214.  */
  1215. static void tree_set_node_expanded_all(struct tree *tree, struct node *node,
  1216.                 bool expanded)
  1217. {
  1218.         for (; node != NULL; node = node->next) {
  1219.                 if (node->expanded != expanded) {
  1220.                         node->expanded = expanded;
  1221.                         tree_recalculate_node_sizes(tree, node, false);
  1222.                 }
  1223.                 if ((node->child != NULL) && (node->expanded))
  1224.                         tree_set_node_expanded_all(tree, node->child, expanded);
  1225.         }
  1226. }
  1227.  
  1228.  
  1229. /**
  1230.  * Updates [all siblings and descendants of] a node to an expansion state.
  1231.  *
  1232.  * \param tree      the tree to update
  1233.  * \param node      the node to set [all siblings and descendants of]
  1234.  * \param expanded  the expansion state to set
  1235.  * \param folder    whether to update folders, if this together with leaf
  1236.  *                  will be false only 'node' will be updated
  1237.  * \param leaf      whether to update leaves (check also description for folder)
  1238.  * \return          whether any changes were made
  1239.  */
  1240. static bool tree_set_node_expanded_internal(struct tree *tree,
  1241.                 struct node *node, bool expanded, bool folder, bool leaf)
  1242. {
  1243.         bool redraw = false;
  1244.         struct node *end = (folder == false && leaf == false) ?
  1245.                 node->next : NULL;
  1246.  
  1247.         if (tree->editing != NULL && node == tree->editing->parent)
  1248.                 tree_stop_edit(tree, false);
  1249.  
  1250.         for (; node != end; node = node->next) {
  1251.                 if ((node->expanded != expanded) && (node != tree->root) &&
  1252.                     ((folder && (node->folder)) ||
  1253.                      (leaf && (!node->folder)) ||
  1254.                      (!folder && !leaf))) {
  1255.                         node->expanded = expanded;
  1256.                         if (node->child != NULL)
  1257.                                 tree_set_node_expanded_all(tree,
  1258.                                                            node->child, false);
  1259.                         if ((node->data.next != NULL) &&
  1260.                             (node->data.next->box.height == 0))
  1261.                                 tree_recalculate_node_sizes(tree, node, true);
  1262.                         else
  1263.                                 tree_recalculate_node_sizes(tree, node, false);
  1264.                         redraw = true;
  1265.                 }
  1266.                 if ((folder || leaf) && (node->child != NULL) &&
  1267.                     (node->expanded))
  1268.                         redraw |= tree_set_node_expanded_internal(tree,
  1269.                                                                   node->child, expanded, folder, leaf);
  1270.         }
  1271.         return redraw;
  1272. }
  1273.  
  1274.  
  1275. /**
  1276.  * Updates [all siblings and descendants of] a node to an expansion state.
  1277.  *
  1278.  * \param tree      the tree to update
  1279.  * \param node      the node to set [all siblings and descendants of]
  1280.  * \param expanded  the expansion state to set
  1281.  * \param folder    whether to update folders, if this together with leaf
  1282.  *                  will be false only 'node' will be updated
  1283.  * \param leaf      whether to update leaves (check also description for folder)
  1284.  */
  1285. void tree_set_node_expanded(struct tree *tree, struct node *node, bool expanded,
  1286.                 bool folder, bool leaf)
  1287. {
  1288.         if (tree_set_node_expanded_internal(tree, node, expanded, folder, leaf))
  1289.                 tree_handle_node_changed(tree, node, false, true);
  1290. }
  1291.  
  1292.  
  1293. /**
  1294.  * Updates a node to an selected state. The required areas of the tree are
  1295.  * redrawn.
  1296.  *
  1297.  * \param tree      the tree to update nodes for, may be NULL
  1298.  * \param node      the node to set all siblings and descendants of
  1299.  * \param all       if true update node together with its siblings and
  1300.  *                  descendants
  1301.  * \param selected  the selection state to set
  1302.  */
  1303. void tree_set_node_selected(struct tree *tree, struct node *node, bool all,
  1304.                 bool selected)
  1305. {
  1306.         struct node *end;
  1307.  
  1308.         if (tree != NULL && node == tree->root)
  1309.                 node = tree->root->child;
  1310.         if (node == NULL)
  1311.                 return;
  1312.  
  1313.         end = all ? NULL : node->next;
  1314.  
  1315.         for (; node != end; node = node->next) {
  1316.                 if (node->selected != selected) {
  1317.                         node->selected = selected;
  1318.                         if (tree != NULL && tree->redraw)
  1319.                                 tree->callbacks->redraw_request(
  1320.                                                 node->data.box.x,
  1321.                                                 node->data.box.y,
  1322.                                                 node->data.box.width,
  1323.                                                 node->data.box.height,
  1324.                                                 tree->client_data);
  1325.                 }
  1326.                 if (all && (node->child != NULL) && (node->expanded))
  1327.                         tree_set_node_selected(tree, node->child, all,
  1328.                                                selected);
  1329.         }
  1330. }
  1331.  
  1332.  
  1333. /**
  1334.  * Sets the sort function for a node
  1335.  *
  1336.  * \param tree  the tree to which 'node' belongs, may be NULL
  1337.  * \param node  the node to be inserted
  1338.  * \param sort  pointer to the sorting function
  1339.  */
  1340. void tree_set_node_sort_function(struct tree *tree, struct node *node,
  1341.                 int (*sort) (struct node *, struct node *))
  1342. {
  1343.         struct node *child;
  1344.  
  1345.         node->sort = sort;
  1346.  
  1347.         if (tree != NULL && tree->editing != NULL)
  1348.                 tree_stop_edit(tree, false);
  1349.  
  1350.         /* the node had already some children so they must get sorted */
  1351.         if (node->child != NULL) {
  1352.  
  1353.                 child = node->child;
  1354.                 node->child = NULL;
  1355.  
  1356.                 while (child != NULL) {
  1357.                         tree_sort_insert(node, child);
  1358.                         child = child->next;
  1359.                 }
  1360.  
  1361.         }
  1362.  
  1363.         if (tree != NULL)
  1364.                 tree_recalculate_node_positions(tree, node->child);
  1365. }
  1366.  
  1367.  
  1368. /**
  1369.  * Sets the delete callback for a node.
  1370.  *
  1371.  * \param node      the node for which the callback is set
  1372.  * \param callback  the callback functions to be set
  1373.  * \param data      user data to be passed to callback
  1374.  */
  1375. void tree_set_node_user_callback(struct node *node,
  1376.                 tree_node_user_callback callback, void *data)
  1377. {
  1378.         node->user_callback = callback;
  1379.         node->callback_data = data;
  1380. }
  1381.  
  1382.  
  1383. /**
  1384.  * Sets the redraw property to the given value. If redraw is true, the tree will
  1385.  * be redrawn on layout/appearance changes.
  1386.  *
  1387.  * \param tree    the tree for which the property is set
  1388.  * \param redraw  the value to set
  1389.  */
  1390. void tree_set_redraw(struct tree *tree, bool redraw)
  1391. {
  1392.         /* the tree might have no graphical representation, do not set the
  1393.            redraw flag in such case */
  1394.         if (tree->callbacks == NULL)
  1395.                 return;
  1396.         tree->redraw = redraw;
  1397. }
  1398.  
  1399.  
  1400. /**
  1401.  * Checks whether a node, its siblings or any children are selected.
  1402.  *
  1403.  * \param node  the root node to check from
  1404.  * \return      whether 'node', its siblings or any children are selected.
  1405.  */
  1406. bool tree_node_has_selection(struct node *node)
  1407. {
  1408.         for (; node != NULL; node = node->next) {
  1409.                 if (node->selected)
  1410.                         return true;
  1411.                 if ((node->child != NULL) && (node->expanded) &&
  1412.                     (tree_node_has_selection(node->child)))
  1413.                         return true;
  1414.         }
  1415.         return false;
  1416. }
  1417.  
  1418.  
  1419. /**
  1420.  * Returns the current value of the nodes deleted property.
  1421.  *
  1422.  * \param node  the node to be checked
  1423.  * \return      the current value of the nodes deleted property
  1424.  */
  1425. bool tree_node_is_deleted(struct node *node)
  1426. {
  1427.         return node->deleted;
  1428. }
  1429.  
  1430.  
  1431. /**
  1432.  * Returns true if the node is a folder
  1433.  *
  1434.  * \param node  the node to be checked
  1435.  * \return      true if the node is a folder, false otherwise
  1436.  */
  1437. bool tree_node_is_folder(struct node *node)
  1438. {
  1439.         return node->folder;
  1440. }
  1441.  
  1442.  
  1443. /**
  1444.  * Returns true if the node is the default folder for a tree
  1445.  *
  1446.  * \param node  the node to be checked
  1447.  * \return      true if the node is a default folder, false otherwise
  1448.  */
  1449. bool tree_node_is_default(struct node *node)
  1450. {
  1451.         return node->def_folder;
  1452. }
  1453.  
  1454.  
  1455. /**
  1456.  * Update the text of a node element if it has changed.
  1457.  *
  1458.  * \param element The node element to update.
  1459.  * \param text The text to update the element with. The ownership of
  1460.  *             this string is taken by this function and must not be
  1461.  *             referred to after the function exits.
  1462.  */
  1463. bool tree_update_element_text(struct tree *tree,
  1464.                 struct node_element *element, char *text)
  1465. {
  1466.         const char *node_text; /* existing node text */
  1467.  
  1468.         if (text == NULL)
  1469.                 return false;
  1470.  
  1471.         if (element == NULL) {
  1472.                 free(text);
  1473.                 return false;
  1474.         }
  1475.  
  1476.         node_text = tree_node_element_get_text(element);
  1477.  
  1478.         if ((node_text == NULL) || (strcmp(node_text, text) != 0)) {
  1479.                 tree_update_node_element(tree, element, text, NULL);
  1480.         } else {
  1481.                 /* text does not need changing, free it */
  1482.                 free(text);
  1483.         }
  1484.         return true;
  1485. }
  1486.  
  1487.  
  1488. /**
  1489.  * Updates the content of a node_element.
  1490.  *
  1491.  * \param tree      the tree owning element, may be NULL
  1492.  * \param element   the element to be updated
  1493.  * \param text      new text to be set, may be NULL
  1494.  * \param bitmap    new bitmap to be set, may be NULL
  1495.  */
  1496. void tree_update_node_element(struct tree *tree, struct node_element *element,
  1497.                 const char *text, void *bitmap)
  1498. {
  1499.         node_callback_resp response;
  1500.         struct node_msg_data msg_data;
  1501.         bool text_changed = false;
  1502.  
  1503.         assert(element != NULL);
  1504.  
  1505.         if (tree != NULL && element == tree->editing)
  1506.                 tree_stop_edit(tree, false);
  1507.  
  1508.         if (text != NULL && (element->type == NODE_ELEMENT_TEXT ||
  1509.                              element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) {
  1510.                 if (element->text != NULL) {
  1511.                         if(strcmp(element->text, text) == 0) text_changed = true;
  1512.  
  1513.                         response = NODE_CALLBACK_NOT_HANDLED;
  1514.                         if (!element->editable &&
  1515.                             element->parent->user_callback !=
  1516.                             NULL) {
  1517.                                 msg_data.msg = NODE_DELETE_ELEMENT_TXT;
  1518.                                 msg_data.flag = element->flag;
  1519.                                 msg_data.node = element->parent;
  1520.                                 msg_data.data.text = (void *)element->text;
  1521.                                 response = element->parent->user_callback(
  1522.                                         element->parent->callback_data,
  1523.                                         &msg_data);
  1524.                         }
  1525.                         if (response != NODE_CALLBACK_HANDLED)
  1526.                                 free((void *)element->text);
  1527.                 }
  1528.                 element->text = text;
  1529.         }
  1530.  
  1531.         if (bitmap != NULL && (element->type == NODE_ELEMENT_BITMAP ||
  1532.                                element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) {
  1533.                 if (element->bitmap != NULL) {
  1534.                         response = NODE_CALLBACK_NOT_HANDLED;
  1535.                         if (element->parent->user_callback != NULL) {
  1536.                                 msg_data.msg = NODE_DELETE_ELEMENT_IMG;
  1537.                                 msg_data.flag = element->flag;
  1538.                                 msg_data.node = element->parent;
  1539.                                 msg_data.data.bitmap = (void *)element->bitmap;
  1540.                                 response = element->parent->user_callback(
  1541.                                         element->parent->callback_data,
  1542.                                         &msg_data);
  1543.                         }
  1544.                         if (response != NODE_CALLBACK_HANDLED)
  1545.                                 free(element->bitmap);
  1546.                 }
  1547.                 else {
  1548.                         /* Increase the box width to accomodate the new icon */
  1549.                         element->box.width += NODE_INSTEP;
  1550.                 }
  1551.  
  1552.                 element->bitmap = bitmap;
  1553.         }
  1554.  
  1555.         tree_handle_node_element_changed(tree, element, text_changed);
  1556. }
  1557.  
  1558.  
  1559. /**
  1560.  * Returns the node element's text
  1561.  *
  1562.  * \return  the node element's text
  1563.  */
  1564. const char *tree_node_element_get_text(struct node_element *element)
  1565. {
  1566.         return element->text;
  1567. }
  1568.  
  1569.  
  1570. /**
  1571.  * Get the root node of a tree
  1572.  *
  1573.  * \param tree  the tree to get the root of
  1574.  * \return      the root of the tree
  1575.  */
  1576. struct node *tree_get_root(struct tree *tree)
  1577. {
  1578.         return tree->root;
  1579. }
  1580.  
  1581.  
  1582. /**
  1583.  * Returns whether the current tree is being edited at this time
  1584.  *
  1585.  * \param tree  the tree to be checked
  1586.  * \return      true if the tree is currently being edited
  1587.  */
  1588. bool tree_is_edited(struct tree *tree)
  1589. {
  1590.         return tree->editing == NULL ? false : true;
  1591. }
  1592.  
  1593.  
  1594. /**
  1595.  * Get the drag state of a tree
  1596.  *
  1597.  * \param tree  the tree to get the state of
  1598.  * \return      drag type (defined in desktop/tree.h)
  1599.  */
  1600. tree_drag_type tree_drag_status(struct tree *tree)
  1601. {
  1602.         return tree->drag;
  1603. }
  1604.  
  1605.  
  1606. /**
  1607.  * Get the default node of a tree for additions
  1608.  *
  1609.  * \param tree  the tree to get the default node of
  1610.  * \return      the default node
  1611.  */
  1612. struct node *tree_get_default_folder_node(struct tree *tree)
  1613. {
  1614.         if (tree->def_folder != NULL) {
  1615.                 return tree->def_folder;
  1616.         } else {
  1617.                 return tree_get_root(tree);
  1618.         }
  1619. }
  1620.  
  1621.  
  1622. /**
  1623.  * Set the default node of a tree to the selected node
  1624.  *
  1625.  * \param tree  the tree to set the default node of
  1626.  * \param node  the node to set as default (NULL for selected node)
  1627.  * \return      success
  1628.  */
  1629. bool tree_set_default_folder_node(struct tree *tree, struct node *node)
  1630. {
  1631.         struct node *sel_node;
  1632.  
  1633.         if (node == NULL) {
  1634.                 sel_node = tree_get_selected_node(tree->root);
  1635.         } else {
  1636.                 sel_node = node;
  1637.         }
  1638.  
  1639.         if((sel_node == NULL) ||
  1640.                 (tree_node_is_folder(sel_node) == false)) {
  1641.                 return false;
  1642.         }
  1643.  
  1644.         tree_clear_default_folder_node(tree);
  1645.  
  1646.         tree->def_folder = sel_node;
  1647.         sel_node->def_folder = true;
  1648.         tree_handle_node_changed(tree, sel_node, true, false);
  1649.  
  1650.         return true;
  1651. }
  1652.  
  1653.  
  1654. /**
  1655.  * Clear the default node of a tree
  1656.  *
  1657.  * \param tree  the tree to clear the default node of
  1658.  */
  1659. void tree_clear_default_folder_node(struct tree *tree)
  1660. {
  1661.         struct node *def_node = NULL;
  1662.         def_node = tree_get_default_folder_node(tree);
  1663.  
  1664.         if (def_node != NULL) {
  1665.                 tree->def_folder = NULL;
  1666.                 def_node->def_folder = false;
  1667.                 tree_handle_node_changed(tree, def_node, true, false);
  1668.         }
  1669. }
  1670.  
  1671.  
  1672. /**
  1673.  * Returns the parent of a node
  1674.  *
  1675.  * \param node  the node to get the parent of
  1676.  * \return      the node's parent
  1677.  */
  1678. struct node *tree_node_get_parent(struct node *node)
  1679. {
  1680.         return node->parent;
  1681. }
  1682.  
  1683.  
  1684. /**
  1685.  * Returns the first child of a node
  1686.  *
  1687.  * \param node  the node to get the child of
  1688.  * \return      the nodes first child
  1689.  */
  1690. struct node *tree_node_get_child(struct node *node)
  1691. {
  1692.         return node->child;
  1693. }
  1694.  
  1695.  
  1696. /**
  1697.  * Returns the closest sibling a node
  1698.  *
  1699.  * \param node  the node to get the sibling of
  1700.  * \return      the nodes sibling
  1701.  */
  1702. struct node *tree_node_get_next(struct node *node)
  1703. {
  1704.         return node->next;
  1705. }
  1706.  
  1707.  
  1708. /**
  1709.  * Draws an element's expansion icon
  1710.  *
  1711.  * \param tree          the tree to draw the expansion for
  1712.  * \param element       the element to draw the expansion for
  1713.  * \param tree_x        X coordinate of the tree
  1714.  * \param tree_y        Y coordinate of the tree
  1715.  * \param ctx           current redraw context
  1716.  */
  1717. static void tree_draw_node_expansion_toggle(struct tree *tree,
  1718.                 struct node *node, int tree_x, int tree_y,
  1719.                 const struct redraw_context *ctx)
  1720. {
  1721.         const struct plotter_table *plot = ctx->plot;
  1722.         int x, y;
  1723.  
  1724.         assert(tree != NULL);
  1725.         assert(node != NULL);
  1726.  
  1727.         if ((node->child != NULL) || (node->data.next != NULL)) {
  1728.                 x = tree_x + node->box.x - (NODE_INSTEP / 2) - 4;
  1729.                 y = tree_y + node->box.y + (TREE_LINE_HEIGHT - 9) / 2;
  1730.                 plot->rectangle(x, y, x + 9, y + 9,
  1731.                                 &plot_style_fill_tree_furniture);
  1732.                 plot->rectangle(x , y, x + 8, y + 8,
  1733.                                 &plot_style_stroke_tree_furniture);
  1734.                 plot->line(x + 2, y + 4, x + 7, y + 4,
  1735.                                 &plot_style_stroke_tree_furniture);
  1736.                 if (!node->expanded)
  1737.                         plot->line(x + 4, y + 2, x + 4, y + 7,
  1738.                                         &plot_style_stroke_tree_furniture);
  1739.  
  1740.         }
  1741.  
  1742. }
  1743.  
  1744.  
  1745. /**
  1746.  * Draws an element, including any expansion icons
  1747.  *
  1748.  * \param tree          the tree to draw an element for
  1749.  * \param element       the element to draw
  1750.  * \param tree_x        X coordinate to draw the tree at (wrt plot origin)
  1751.  * \param tree_y        Y coordinate to draw the tree at (wrt plot origin)
  1752.  * \param clip          clipping rectangle (wrt plot origin)
  1753.  * \param ctx           current redraw context
  1754.  */
  1755. static void tree_draw_node_element(struct tree *tree,
  1756.                 struct node_element *element, int tree_x, int tree_y,
  1757.                 const struct rect *clip, const struct redraw_context *ctx)
  1758. {
  1759.         const struct plotter_table *plot = ctx->plot;
  1760.         struct bitmap *bitmap = NULL;
  1761.         int x, y, width;
  1762.         bool selected = false;
  1763.         bool def_folder = false;
  1764.         hlcache_handle *icon;
  1765.         plot_font_style_t *fstyle;
  1766.         const int icon_inset = (TREE_LINE_HEIGHT - TREE_ICON_SIZE) / 2;
  1767.  
  1768.         assert(tree != NULL);
  1769.         assert(element != NULL);
  1770.         assert(element->parent != NULL);
  1771.  
  1772.         x = tree_x + element->box.x;
  1773.         y = tree_y + element->box.y;
  1774.         width = element->box.width;
  1775.         if (&element->parent->data == element) {
  1776.                 if (element->parent->selected)
  1777.                         selected = true;
  1778.                 if (element->parent->def_folder)
  1779.                         def_folder = true;
  1780.         }
  1781.  
  1782.         switch (element->type) {
  1783.         case NODE_ELEMENT_TEXT_PLUS_ICON:
  1784.                 icon = element->bitmap;
  1785.                 if (icon != NULL && (content_get_status(icon) ==
  1786.                                 CONTENT_STATUS_READY ||
  1787.                                 content_get_status(icon) ==
  1788.                                 CONTENT_STATUS_DONE) &&
  1789.                                 x + TREE_ICON_SIZE > clip->x0 &&
  1790.                                 x < clip->x1) {
  1791.                         struct rect c;
  1792.                         /* Clip to image area */
  1793.                         c.x0 = x;
  1794.                         c.y0 = y + icon_inset;
  1795.                         c.x1 = x + TREE_ICON_SIZE;
  1796.                         c.y1 = y + icon_inset + TREE_ICON_SIZE;
  1797.                         if (c.x0 < clip->x0) c.x0 = clip->x0;
  1798.                         if (c.y0 < clip->y0) c.y0 = clip->y0;
  1799.                         if (c.x1 > clip->x1) c.x1 = clip->x1;
  1800.                         if (c.y1 > clip->y1) c.y1 = clip->y1;
  1801.  
  1802.                         if (c.x1 > c.x0 && c.y1 > c.y0) {
  1803.                                 /* Valid clip rectangles only */
  1804.                                 struct content_redraw_data data;
  1805.  
  1806.                                 plot->clip(&c);
  1807.  
  1808.                                 data.x = x;
  1809.                                 data.y = y + icon_inset;
  1810.                                 data.width = TREE_ICON_SIZE;
  1811.                                 data.height = TREE_ICON_SIZE;
  1812.  
  1813.                                 data.background_colour = 0xFFFFFF;
  1814.                                 data.scale = 1;
  1815.                                 data.repeat_x = false;
  1816.                                 data.repeat_y = false;
  1817.  
  1818.                                 content_redraw(icon, &data, &c, ctx);
  1819.  
  1820.                                 /* Restore previous clipping area */
  1821.                                 plot->clip(clip);
  1822.                         }
  1823.                 }
  1824.  
  1825.                 x += NODE_INSTEP;
  1826.                 width -= NODE_INSTEP;
  1827.  
  1828.                 /* fall through */
  1829.         case NODE_ELEMENT_TEXT:
  1830.                 if (element->text == NULL || clip->x1 < x)
  1831.                         break;
  1832.  
  1833.                 if (element == tree->editing)
  1834.                         return;
  1835.  
  1836.                 if (selected) {
  1837.                         if (def_folder == true)
  1838.                                 fstyle = &plot_fstyle_selected_def_folder;
  1839.                         else
  1840.                                 fstyle = &plot_fstyle_selected;
  1841.  
  1842.                         plot->rectangle(x, y, x + width,
  1843.                                        y + element->box.height,
  1844.                                        &plot_style_fill_tree_selected);
  1845.                 } else {
  1846.                 if (def_folder == true)
  1847.                         fstyle = &plot_fstyle_def_folder;
  1848.                 else
  1849.                         fstyle = &plot_fstyle;
  1850.                 }
  1851.  
  1852.                 plot->text(x + 4, y + (TREE_LINE_HEIGHT * 3 + 2) / 4,
  1853.                                 element->text, strlen(element->text),
  1854.                                 fstyle);
  1855.                 break;
  1856.         case NODE_ELEMENT_BITMAP:
  1857.                 bitmap = element->bitmap;
  1858.                 if (bitmap == NULL)
  1859.                         break;
  1860.                 plot->bitmap(x, y, element->box.width - 1,
  1861.                             element->box.height - 2,
  1862.                             bitmap, 0xFFFFFF, BITMAPF_NONE);
  1863.                 if (!(tree->flags & TREE_NO_FURNITURE))
  1864.                         plot->rectangle(x, y, x + element->box.width - 1,
  1865.                                        y + element->box.height - 3,
  1866.                                        &plot_style_stroke_tree_furniture);
  1867.  
  1868.                 break;
  1869.         }
  1870.  
  1871. }
  1872.  
  1873.  
  1874. /**
  1875.  * Redraws a node.
  1876.  *
  1877.  * \param tree          the tree to draw
  1878.  * \param node          the node to draw children and siblings of
  1879.  * \param tree_x        X coordinate to draw the tree at (wrt plot origin)
  1880.  * \param tree_y        Y coordinate to draw the tree at (wrt plot origin)
  1881.  * \param clip          clipping rectangle (wrt plot origin)
  1882.  * \param ctx           current redraw context
  1883.  */
  1884. static void tree_draw_node(struct tree *tree, struct node *node,
  1885.                 int tree_x, int tree_y, struct rect clip,
  1886.                 const struct redraw_context *ctx)
  1887. {
  1888.         const struct plotter_table *plot = ctx->plot;
  1889.         struct node_element *element;
  1890.         struct node *parent;
  1891.         int x0, y0, x1, y1;
  1892.         struct rect node_extents;
  1893.  
  1894.         assert(tree != NULL);
  1895.         assert(node != NULL);
  1896.  
  1897.         /* Find node's extents, including children's area */
  1898.         node_extents.x0 = tree_x + node->box.x - NODE_INSTEP;
  1899.         node_extents.y0 = tree_y + node->box.y;
  1900.         node_extents.x1 = tree_x + node->box.x + node->box.width + NODE_INSTEP;
  1901.         if (node->next != NULL)
  1902.                 node_extents.y1 = tree_y + node->next->box.y;
  1903.         else
  1904.                 node_extents.y1 = tree_y + node->box.y + node->box.height;
  1905.  
  1906.         /* Nothing to draw, if node is outside clip region */
  1907.         if ((node_extents.x1 < clip.x0) && (node_extents.y1 < clip.y0) &&
  1908.                         (node_extents.x0 > clip.x1) &&
  1909.                         (node_extents.y0 > clip.y1)) {
  1910.                 return;
  1911.         }
  1912.  
  1913.         /* Intersect clip region with node's extents */
  1914.         if (clip.x0 < node_extents.x0) clip.x0 = node_extents.x0;
  1915.         if (clip.y0 < node_extents.y0) clip.y0 = node_extents.y0;
  1916.         if (clip.x1 > node_extents.x1) clip.x1 = node_extents.x1;
  1917.         if (clip.y1 > node_extents.y1) clip.y1 = node_extents.y1;
  1918.  
  1919.         if (clip.x0 >= clip.x1 || clip.y0 >= clip.y1) {
  1920.                 /* Invalid clip rectangle */
  1921.                 return;
  1922.         }
  1923.  
  1924.         /* Set up the clipping area */
  1925.         plot->clip(&clip);
  1926.  
  1927.         /* Draw node's furniture */
  1928.         if (!(tree->flags & TREE_NO_FURNITURE)) {
  1929.                 /* Display furniture */
  1930.                 if (node->previous != NULL) {
  1931.                         /* There is a node above this
  1932.                          * Display furniture; line connecting up to previous */
  1933.                         x0 = x1 = tree_x + node->box.x - (NODE_INSTEP / 2);
  1934.                         y0 = tree_y + node->previous->box.y;
  1935.                         y1 = tree_y + node->box.y + (TREE_LINE_HEIGHT / 2);
  1936.                         plot->line(x0, y0, x1, y1,
  1937.                                         &plot_style_stroke_tree_furniture);
  1938.                 }
  1939.                 if (node->next != NULL) {
  1940.                         /* There is a node below this
  1941.                          * Display furniture; line connecting down to next */
  1942.                         x0 = x1 = tree_x + node->box.x - (NODE_INSTEP / 2);
  1943.                         y0 = tree_y + node->box.y + (TREE_LINE_HEIGHT / 2);
  1944.                         y1 = tree_y + node->next->box.y;
  1945.                         plot->line(x0, y0, x1, y1,
  1946.                                         &plot_style_stroke_tree_furniture);
  1947.                 }
  1948.  
  1949.                 parent = node->parent;
  1950.                 if ((parent != NULL) && (parent != tree->root) &&
  1951.                                 (parent->child == node)) {
  1952.                         /* Node is first child */
  1953.                         x0 = x1 = tree_x + parent->box.x + (NODE_INSTEP / 2);
  1954.                         y0 = tree_y + parent->data.box.y +
  1955.                                         parent->data.box.height;
  1956.                         y1 = y0 + (TREE_LINE_HEIGHT / 2);
  1957.                         plot->line(x0, y0, x1, y1,
  1958.                                         &plot_style_stroke_tree_furniture);
  1959.                 }
  1960.                 /* Line from expansion toggle to icon */
  1961.                 x0 = tree_x + node->box.x - (NODE_INSTEP / 2);
  1962.                 x1 = x0 + (NODE_INSTEP / 2) - 2;
  1963.                 y0 = y1 = tree_y + node->data.box.y + node->data.box.height -
  1964.                                 (TREE_LINE_HEIGHT / 2);
  1965.                 plot->line(x0, y0, x1, y1, &plot_style_stroke_tree_furniture);
  1966.  
  1967.                 tree_draw_node_expansion_toggle(tree, node,
  1968.                                 tree_x, tree_y, ctx);
  1969.         }
  1970.  
  1971.         /* Draw node's element(s)
  1972.          * NOTE: node's children are handled later in tree_draw_tree() */
  1973.         if (node->expanded) {
  1974.                 for (element = &node->data; element != NULL;
  1975.                                 element = element->next) {
  1976.                         /* Draw each element of expanded node */
  1977.                         tree_draw_node_element(tree, element, tree_x, tree_y,
  1978.                                         &clip, ctx);
  1979.                 }
  1980.         } else {
  1981.                 /* Draw main title element of node */
  1982.                 tree_draw_node_element(tree, &node->data, tree_x, tree_y,
  1983.                                 &clip, ctx);
  1984.         }
  1985. }
  1986.  
  1987.  
  1988. /**
  1989.  * Redraws a node's descendants.
  1990.  *
  1991.  * \param tree          the tree to draw
  1992.  * \param node          the node to draw children and siblings of
  1993.  * \param tree_x        X coordinate to draw the tree at (wrt plot origin)
  1994.  * \param tree_y        Y coordinate to draw the tree at (wrt plot origin)
  1995.  * \param clip          clipping rectangle (wrt plot origin)
  1996.  * \param ctx           current redraw context
  1997.  */
  1998. static void tree_draw_tree(struct tree *tree, struct node *node,
  1999.                 int tree_x, int tree_y, struct rect clip,
  2000.                 const struct redraw_context *ctx)
  2001. {
  2002.         struct node *child;
  2003.  
  2004.         assert(tree != NULL);
  2005.         assert(node != NULL);
  2006.  
  2007.         for (child = node->child; child != NULL; child = child->next) {
  2008.                 /* Draw children that are inside the clip region */
  2009.  
  2010.                 if (child->next != NULL &&
  2011.                                 (child->next->box.y + tree_y < clip.y0))
  2012.                         /* Child is above clip region */
  2013.                         continue;
  2014.                 if (child->box.y + tree_y > clip.y1)
  2015.                         /* Child is below clip region
  2016.                          * further siblings will be too */
  2017.                         return;
  2018.  
  2019.                 /* Draw current child */
  2020.                 tree_draw_node(tree, child, tree_x, tree_y, clip, ctx);
  2021.                 /* And its children */
  2022.                 if ((child->child != NULL) && (child->expanded)) {
  2023.                         /* Child has children and they are visible */
  2024.                         tree_draw_tree(tree, child, tree_x, tree_y, clip, ctx);
  2025.                 }
  2026.         }
  2027. }
  2028.  
  2029.  
  2030. /**
  2031.  * Redraws a tree.
  2032.  *
  2033.  * \param tree          the tree to draw
  2034.  * \param x             X coordinate to draw the tree at (wrt plot origin)
  2035.  * \param y             Y coordinate to draw the tree at (wrt plot origin)
  2036.  * \param clip_x        minimum x of the clipping rectangle (wrt tree origin)
  2037.  * \param clip_y        minimum y of the clipping rectangle (wrt tree origin)
  2038.  * \param clip_width    width of the clipping rectangle
  2039.  * \param clip_height   height of the clipping rectangle
  2040.  * \param ctx           current redraw context
  2041.  */
  2042. void tree_draw(struct tree *tree, int x, int y,
  2043.                 int clip_x, int clip_y, int clip_width, int clip_height,
  2044.                 const struct redraw_context *ctx)
  2045. {
  2046.         struct redraw_context new_ctx = *ctx;
  2047.         struct rect clip;
  2048.  
  2049.         assert(tree != NULL);
  2050.         assert(tree->root != NULL);
  2051.  
  2052.         /* Start knockout rendering if it's available for this plotter */
  2053.         if (ctx->plot->option_knockout)
  2054.                 knockout_plot_start(ctx, &new_ctx);
  2055.  
  2056.         /* Set up clip rectangle */
  2057.         clip.x0 = x + clip_x;
  2058.         clip.y0 = y + clip_y;
  2059.         clip.x1 = clip.x0 + clip_width;
  2060.         clip.y1 = clip.y0 + clip_height;
  2061.         new_ctx.plot->clip(&clip);
  2062.  
  2063.         /* Flat fill extents of clipping area */
  2064.         new_ctx.plot->rectangle(clip.x0, clip.y0, clip.x1, clip.y1,
  2065.                        &plot_style_fill_tree_background);
  2066.  
  2067.         /* don't draw empty trees or trees with redraw flag set to false */
  2068.         if (tree->root->child != NULL && tree->redraw) {
  2069.  
  2070.                 /* Draw the tree */
  2071.                 tree_draw_tree(tree, tree->root, x, y, clip, &new_ctx);
  2072.  
  2073.                 /* Draw textarea, if present */
  2074.                 if (tree->editing != NULL) {
  2075.                         x = x + tree->editing->box.x;
  2076.                         y = y + tree->editing->box.y;
  2077.                         if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
  2078.                                 x += NODE_INSTEP;
  2079.                         textarea_redraw(tree->textarea, x, y,
  2080.                                         plot_style_fill_tree_background.
  2081.                                                         fill_colour,
  2082.                                         &clip, &new_ctx);
  2083.                 }
  2084.         }
  2085.  
  2086.         /* Rendering complete */
  2087.         if (ctx->plot->option_knockout)
  2088.                 knockout_plot_end();
  2089. }
  2090.  
  2091.  
  2092. /**
  2093.  * Finds a node element from a node with a specific user_type
  2094.  *
  2095.  * \param node  the node to examine
  2096.  * \param flag  user assinged flag used is searches
  2097.  * \param after if this is not NULL the search will start after the given
  2098.  *              node_element
  2099.  * \return      the corresponding element
  2100.  */
  2101. struct node_element *tree_node_find_element(struct node *node,
  2102.                 unsigned int flag, struct node_element *after)
  2103. {
  2104.         struct node_element *element;
  2105.  
  2106.         if (after == NULL)
  2107.                 element = &node->data;
  2108.         else {
  2109.                 assert(after->parent == node);
  2110.                 element = after->next;
  2111.         }
  2112.  
  2113.         for (; element != NULL; element = element->next)
  2114.                 if (element->flag == flag) return element;
  2115.  
  2116.         return NULL;
  2117. }
  2118.  
  2119.  
  2120. /**
  2121.  * Deletes all selected nodes from the tree.
  2122.  *
  2123.  * \param tree  the tree to delete from
  2124.  * \param node  the node to delete
  2125.  */
  2126. void tree_delete_selected_nodes(struct tree *tree, struct node *node)
  2127. {
  2128.         struct node *next;
  2129.         int y = node->box.y;
  2130.         int height = tree->height;
  2131.         int width = tree->width;
  2132.         bool redraw_setting = tree->redraw;
  2133.  
  2134.         tree->redraw = false;
  2135.  
  2136.         if (node == tree->root) {
  2137.                 if (node->child != NULL)
  2138.                         tree_delete_selected_nodes(tree, node->child);
  2139.  
  2140.                 tree->redraw = redraw_setting;
  2141.  
  2142.                 if (tree->redraw)
  2143.                         tree->callbacks->redraw_request(0, y,
  2144.                                         width, height,
  2145.                                         tree->client_data);
  2146.                 return;
  2147.         }
  2148.  
  2149.         while (node != NULL) {
  2150.                 next = node->next;
  2151.                 if (node->selected)
  2152.                         tree_delete_node(tree, node, false);
  2153.                 else if (node->child != NULL)
  2154.                         tree_delete_selected_nodes(tree, node->child);
  2155.                 node = next;
  2156.         }
  2157.  
  2158.         tree->redraw = redraw_setting;
  2159.  
  2160.         if (tree->redraw)
  2161.                 tree->callbacks->redraw_request(0, y,
  2162.                                 width, height,
  2163.                                 tree->client_data);
  2164. }
  2165.  
  2166.  
  2167. /**
  2168.  * Returns the selected node, or NULL if multiple nodes are selected.
  2169.  *
  2170.  * \param node  the node to search sibling and children
  2171.  * \return      the selected node, or NULL if multiple nodes are selected
  2172.  */
  2173. struct node *tree_get_selected_node(struct node *node)
  2174. {
  2175.         struct node *result = NULL;
  2176.         struct node *temp;
  2177.  
  2178.         for (; node != NULL; node = node->next) {
  2179.                 if (node->selected) {
  2180.                         if (result != NULL)
  2181.                                 return NULL;
  2182.                         result = node;
  2183.                 }
  2184.                 if ((node->child != NULL) && (node->expanded)) {
  2185.                         temp = tree_get_selected_node(node->child);
  2186.                         if (temp != NULL) {
  2187.                                 if (result != NULL)
  2188.                                         return NULL;
  2189.                                 else
  2190.                                         result = temp;
  2191.                         }
  2192.                 }
  2193.         }
  2194.         return result;
  2195. }
  2196.  
  2197.  
  2198. /**
  2199.  * Finds a node element at a specific location.
  2200.  *
  2201.  * \param node       the root node to check from
  2202.  * \param x          the x co-ordinate
  2203.  * \param y          the y co-ordinate
  2204.  * \param expansion_toggle  whether the coordinate was in an expansion toggle
  2205.  * \return the node at the specified position, or NULL for none
  2206.  */
  2207. static struct node_element *tree_get_node_element_at(struct node *node,
  2208.                 int x, int y, bool *expansion_toggle)
  2209. {
  2210.         struct node_element *element;
  2211.         int x0, x1, y0, y1;
  2212.  
  2213.         *expansion_toggle = false;
  2214.         for (; node != NULL; node = node->next) {
  2215.                 if (node->box.y > y) return NULL;
  2216.                 if ((node->box.x - NODE_INSTEP < x) && (node->box.y < y) &&
  2217.                     (node->box.x + node->box.width >= x) &&
  2218.                     (node->box.y + node->box.height >= y)) {
  2219.                         if (node->expanded) {
  2220.                                 for (element = &node->data; element != NULL;
  2221.                                      element = element->next) {
  2222.                                         x0 = element->box.x;
  2223.                                         y0 = element->box.y;
  2224.                                         x1 = element->box.x +
  2225.                                                 element->box.width;
  2226.                                         y1 = element->box.y +
  2227.                                                 element->box.height;
  2228.                                         if ((x0 < x) && (y0 < y) && (x1 >= x)
  2229.                                             && (y1 >= y))
  2230.                                                 return element;
  2231.                                 }
  2232.                         } else {
  2233.                                 x0 = node->data.box.x;
  2234.                                 y0 = node->data.box.y;
  2235.                                 x1 = node->data.box.x + node->data.box.width;
  2236.                                 y1 = node->data.box.y + node->data.box.height;
  2237.                                 if ((x0 < x) && (y0 < y) && (x1 >= x) &&
  2238.                                     (y1>= y))
  2239.                                         return &node->data;
  2240.                         }
  2241.                         if (((node->child != NULL) ||
  2242.                              (node->data.next != NULL)) &&
  2243.                             (node->data.box.x - NODE_INSTEP + 4 < x)
  2244.                             && (node->data.box.y + 4 < y) &&
  2245.                             (node->data.box.x > x) &&
  2246.                             (node->data.box.y + TREE_LINE_HEIGHT > y)) {
  2247.                                 /* Node either has node children, or node
  2248.                                  * has more than one element.
  2249.                                  * Coordinate is over node expansion toggle area
  2250.                                  */
  2251.                                 *expansion_toggle = true;
  2252.                                 return &node->data;
  2253.                         }
  2254.                 }
  2255.  
  2256.                 element = tree_get_node_element_at(node->child, x, y,
  2257.                                 expansion_toggle);
  2258.                 if ((node->child != NULL) && (node->expanded) &&
  2259.                     (element != NULL))
  2260.                         return element;
  2261.         }
  2262.         return NULL;
  2263. }
  2264.  
  2265.  
  2266. /**
  2267.  * Finds a node at a specific location.
  2268.  *
  2269.  * \param root       the root node to check from
  2270.  * \param x          the x co-ordinate
  2271.  * \param y          the y co-ordinate
  2272.  * \param expansion_toggle  whether the coordinate was in an expansion toggle
  2273.  * \return the node at the specified position, or NULL for none
  2274.  */
  2275. static struct node *tree_get_node_at(struct node *root, int x, int y,
  2276.                 bool *expansion_toggle)
  2277. {
  2278.         struct node_element *result;
  2279.  
  2280.         if ((result = tree_get_node_element_at(root, x, y, expansion_toggle)))
  2281.                 return result->parent;
  2282.         return NULL;
  2283. }
  2284.  
  2285.  
  2286. /**
  2287.  * Gets link characteristics to insert a node at a specified position.
  2288.  *
  2289.  * \param tree    the tree to find link information for
  2290.  * \param x       the x co-ordinate
  2291.  * \param y       the y co-ordinate
  2292.  * \param before  set to whether the node should be linked before on exit
  2293.  * \return        the node to link with
  2294.  */
  2295. struct node *tree_get_link_details(struct tree *tree, int x, int y,
  2296.                 bool *before)
  2297. {
  2298.         struct node *node = NULL;
  2299.         bool expansion_toggle;
  2300.  
  2301.         assert(tree != NULL);
  2302.         assert(tree->root != NULL);
  2303.  
  2304.         *before = false;
  2305.         if (tree->root->child != NULL)
  2306.                 node = tree_get_node_at(tree->root->child, x, y,
  2307.                                 &expansion_toggle);
  2308.         if ((node == NULL) || (expansion_toggle))
  2309.                 return tree->root;
  2310.  
  2311.         if (y < (node->box.y + (node->box.height / 2))) {
  2312.                 *before = true;
  2313.         } else if ((node->folder) && (node->expanded) &&
  2314.                    (node->child != NULL)) {
  2315.                 node = node->child;
  2316.                 *before = true;
  2317.         }
  2318.         return node;
  2319. }
  2320.  
  2321.  
  2322. /**
  2323.  * Launches all the selected nodes of the tree
  2324.  *
  2325.  * \param tree  the tree for which all nodes will be launched
  2326.  * \param node  the node which will be checked together with its children
  2327.  * \param tabs  launch node in a new tab instead of a new window
  2328.  */
  2329. static void tree_launch_selected_internal(struct tree *tree, struct node *node,
  2330.                 bool tabs)
  2331. {
  2332.         struct node_msg_data msg_data;
  2333.  
  2334.         msg_data.data.bw = NULL;
  2335.  
  2336.         for (; node != NULL; node = node->next) {
  2337.                 if (node->selected && node->user_callback != NULL) {
  2338.                         msg_data.msg = NODE_LAUNCH;
  2339.                         if (tabs == true) {
  2340.                                 msg_data.flag = TREE_ELEMENT_LAUNCH_IN_TABS;
  2341.                         } else {
  2342.                                 msg_data.flag = TREE_ELEMENT_TITLE;
  2343.                         }
  2344.  
  2345.                         msg_data.node = node;
  2346.                         node->user_callback(node->callback_data, &msg_data);
  2347.                 }
  2348.                 if (node->child != NULL)
  2349.                         tree_launch_selected_internal(tree, node->child, tabs);
  2350.         }
  2351. }
  2352.  
  2353.  
  2354. /**
  2355.  * Launches all the selected nodes of the tree
  2356.  *
  2357.  * \param tree  the tree for which all nodes will be launched
  2358.  * \param tabs  launch nodes in new tabs instead of new windows
  2359.  */
  2360. void tree_launch_selected(struct tree *tree, bool tabs)
  2361. {
  2362.         if (tree->root->child != NULL)
  2363.                 tree_launch_selected_internal(tree, tree->root->child, tabs);
  2364. }
  2365.  
  2366.  
  2367. /**
  2368.  * Updates the node at position x,y to a selected state.
  2369.  * The required areas of the tree are redrawn.
  2370.  *
  2371.  * \param tree      the tree to update nodes for, may be NULL
  2372.  * \param x             x position in tree
  2373.  * \param y             y position in tree
  2374.  * \param selected  the selection state to set
  2375.  */
  2376. void tree_set_node_selected_at(struct tree *tree, int x, int y, bool selected)
  2377. {
  2378.         bool expansion_toggle;
  2379.         struct node *node;
  2380.  
  2381.         node = tree_get_node_at(tree->root, x, y, &expansion_toggle);
  2382.  
  2383.         if ((node == NULL) || (expansion_toggle == true))
  2384.                 return;
  2385.  
  2386.         tree_set_node_selected(tree, node, false, selected);
  2387. }
  2388.  
  2389.  
  2390. /**
  2391.  * Handles a mouse action for a tree
  2392.  *
  2393.  * \param tree   the tree to handle a click for
  2394.  * \param mouse  the mouse state
  2395.  * \param x      X coordinate of mouse action
  2396.  * \param y      Y coordinate of mouse action
  2397.  * \return       whether the click was handled
  2398.  */
  2399. bool tree_mouse_action(struct tree *tree, browser_mouse_state mouse, int x,
  2400.                 int y)
  2401. {
  2402.         bool expansion_toggle;
  2403.         struct node *node;
  2404.         struct node *last;
  2405.         struct node_element *element;
  2406.         struct node_msg_data msg_data;
  2407.  
  2408.         bool double_click_1 = mouse & BROWSER_MOUSE_DOUBLE_CLICK &&
  2409.                         mouse & BROWSER_MOUSE_CLICK_1;
  2410.         bool double_click_2 = mouse & BROWSER_MOUSE_DOUBLE_CLICK &&
  2411.                         mouse & BROWSER_MOUSE_CLICK_2;
  2412.  
  2413.         assert(tree != NULL);
  2414.         assert(tree->root != NULL);
  2415.  
  2416.         if (tree->root->child == NULL)
  2417.                 return true;
  2418.  
  2419.         element = tree_get_node_element_at(tree->root->child, x, y,
  2420.                         &expansion_toggle);
  2421.  
  2422.         /* pass in-textarea mouse action and drags which started in it
  2423.            to the textarea */
  2424.         if (tree->editing != NULL) {
  2425.                 int x0, x1, y0, y1;
  2426.                 x0 = tree->editing->box.x;
  2427.                 if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
  2428.                         x0 += NODE_INSTEP;
  2429.                 x1 = tree->editing->box.x + tree->editing->box.width;
  2430.                 y0 = tree->editing->box.y;
  2431.                 y1 = tree->editing->box.y + tree->ta_height;
  2432.  
  2433.                 if (tree->drag == TREE_TEXTAREA_DRAG &&
  2434.                                 (mouse & (BROWSER_MOUSE_HOLDING_1 |
  2435.                                 BROWSER_MOUSE_HOLDING_2))) {
  2436.                         /* Track the drag path */
  2437.                         textarea_mouse_action(tree->textarea, mouse,
  2438.                                               x - x0, y - y0);
  2439.                         return true;
  2440.                 }
  2441.  
  2442.                 if ((x >= x0) && (x < x1) && (y >= y0) && (y < y1)) {
  2443.                         textarea_mouse_action(tree->textarea, mouse,
  2444.                                               x - x0, y - y0);
  2445.                         return true;
  2446.  
  2447.                 }
  2448.         }
  2449.  
  2450.         /* we are not interested in the drag path, return */
  2451.         if (mouse & (BROWSER_MOUSE_HOLDING_1 | BROWSER_MOUSE_HOLDING_2))
  2452.                 return true;
  2453.  
  2454.         /* cancel edit */
  2455.         if (tree->editing != NULL)
  2456.                 tree_stop_edit(tree, false);
  2457.  
  2458.         /* no item either means cancel selection on (select) click or a drag */
  2459.         if (element == NULL) {
  2460.                 if (tree->flags & TREE_SINGLE_SELECT) {
  2461.                         tree_set_node_selected(tree, tree->root->child, true,
  2462.                                                false);
  2463.                         return true;
  2464.                 }
  2465.                 if (mouse & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_DRAG_1))
  2466.                         tree_set_node_selected(tree, tree->root->child, true,
  2467.                                                false);
  2468.                 if (mouse & (BROWSER_MOUSE_DRAG_1 | BROWSER_MOUSE_DRAG_2)) {
  2469.  
  2470.                         /** @todo the tree window has to scroll the tree when
  2471.                          * mouse reaches border while dragging this isn't
  2472.                          * solved for the browser window too.
  2473.                          */
  2474.                         tree->drag = TREE_SELECT_DRAG;
  2475.                 }
  2476.                 return true;
  2477.         }
  2478.  
  2479.         node = element->parent;
  2480.  
  2481.         /* A click on expansion toggle or double click on folder toggles node
  2482.          * expansion */
  2483.         if (((expansion_toggle) && (mouse & (BROWSER_MOUSE_CLICK_1 |
  2484.                         BROWSER_MOUSE_CLICK_2))) ||
  2485.                         (((!expansion_toggle) && (node->child != NULL)) &&
  2486.                         (double_click_1 || double_click_2))) {
  2487.  
  2488.                 /* clear any selection */
  2489.                 tree_set_node_selected(tree, tree->root->child, true, false);
  2490.  
  2491.                 /* expand / contract node and redraw */
  2492.                 tree_set_node_expanded(tree, node, !node->expanded,
  2493.                                        false, false);
  2494.  
  2495.                 /* find the last child node if expanded */
  2496.                 last = node;
  2497.                 if ((last->child != NULL) && (last->expanded)) {
  2498.                         last = last->child;
  2499.                         while ((last->next != NULL) ||
  2500.                                ((last->child != NULL) &&
  2501.                                 (last->expanded))) {
  2502.                                 if (last->next != NULL)
  2503.                                         last = last->next;
  2504.                                 else
  2505.                                         last = last->child;
  2506.                         }
  2507.                 }
  2508.                 /* scroll to the bottom element then back to the top */
  2509.                 element = &last->data;
  2510.                 if (last->expanded)
  2511.                         for (; element->next != NULL; element = element->next);
  2512.                 tree->callbacks->scroll_visible(element->box.y,
  2513.                                                 element->box.height,
  2514.                                                 tree->client_data);
  2515.                 tree->callbacks->scroll_visible(node->data.box.y,
  2516.                                                 node->data.box.height,
  2517.                                                 tree->client_data);
  2518.                 return true;
  2519.         }
  2520.  
  2521.         /* no use for any other expansion toggle click */
  2522.         if (expansion_toggle)
  2523.                 return true;
  2524.  
  2525.         /* single/double ctrl+click or alt+click starts editing */
  2526.         if ((element->editable) && (!tree->editing) &&
  2527.             ((element->type == NODE_ELEMENT_TEXT) ||
  2528.              (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)) &&
  2529.             (mouse & BROWSER_MOUSE_CLICK_1 || double_click_1) &&
  2530.             (mouse & BROWSER_MOUSE_MOD_2 ||
  2531.              mouse & BROWSER_MOUSE_MOD_3)) {
  2532.                 tree_set_node_selected(tree, tree->root->child, true, false);
  2533.                 tree_start_edit(tree, element);
  2534.                 return true;
  2535.         }
  2536.  
  2537.         /* double click launches the leaf */
  2538.         if (double_click_1 || double_click_2) {
  2539.                 if (node->user_callback == NULL)
  2540.                         return false;
  2541.                 msg_data.msg = NODE_LAUNCH;
  2542.                 msg_data.flag = TREE_ELEMENT_TITLE;
  2543.                 msg_data.node = node;
  2544.                 if (node->user_callback(node->callback_data, &msg_data) !=
  2545.                     NODE_CALLBACK_HANDLED)
  2546.                         return false;
  2547.  
  2548.                 return true;
  2549.         }
  2550.  
  2551.         /* single click (select) cancels current selection and selects item */
  2552.         if (mouse & BROWSER_MOUSE_CLICK_1 || (mouse & BROWSER_MOUSE_CLICK_2 &&
  2553.                                               tree->flags & TREE_SINGLE_SELECT)) {
  2554.                 if (tree->flags & TREE_NO_SELECT)
  2555.                         return true;
  2556.                 if (!node->selected) {
  2557.                         tree_set_node_selected(tree, tree->root->child, true,
  2558.                                                false);
  2559.                         node->selected = true;
  2560.                         tree_handle_node_element_changed(tree, &node->data, false);
  2561.                 }
  2562.                 return true;
  2563.         }
  2564.  
  2565.         /* single click (adjust) toggles item selection */
  2566.         if (mouse & BROWSER_MOUSE_CLICK_2) {
  2567.                 if (tree->flags & TREE_NO_SELECT)
  2568.                         return true;
  2569.                 node->selected = !node->selected;
  2570.                 tree_handle_node_element_changed(tree, &node->data, false);
  2571.                 return true;
  2572.         }
  2573.  
  2574.         /* drag starts a drag operation */
  2575.         if ((!tree->editing) && (mouse & (BROWSER_MOUSE_DRAG_1 |
  2576.                                           BROWSER_MOUSE_DRAG_2))) {
  2577.                 if (tree->flags & TREE_NO_DRAGS)
  2578.                         return true;
  2579.  
  2580.                 if (!node->selected) {
  2581.                         tree_set_node_selected(tree, tree->root->child, true,
  2582.                                                false);
  2583.                         node->selected = true;
  2584.                         tree_handle_node_element_changed(tree, &node->data, false);
  2585.                 }
  2586.  
  2587.                 if (tree->flags & TREE_MOVABLE)
  2588.                         tree->drag = TREE_MOVE_DRAG;
  2589.                 else tree->drag = TREE_UNKNOWN_DRAG;
  2590.  
  2591.                 return true;
  2592.         }
  2593.  
  2594.  
  2595.         return false;
  2596. }
  2597.  
  2598.  
  2599. /**
  2600.  * Updates the selected state for a region of nodes.
  2601.  *
  2602.  * \param tree    the tree to update
  2603.  * \param node    the node to update children and siblings of
  2604.  * \param y       the minimum y of the selection rectangle
  2605.  * \param height  the height of the selection rectangle
  2606.  * \param invert  whether to invert the selected state
  2607.  */
  2608. static void tree_handle_selection_area_node(struct tree *tree,
  2609.                 struct node *node, int y, int height, bool invert)
  2610. {
  2611.         struct node_element *element;
  2612.         struct node *update;
  2613.         int y_max;
  2614.         int y0, y1;
  2615.  
  2616.         assert(tree != NULL);
  2617.         assert(node != NULL);
  2618.  
  2619.         y_max = y + height;
  2620.  
  2621.         for (; node != NULL; node = node->next) {
  2622.                 if (node->box.y > y_max) return;
  2623.                 y0 = node->box.y;
  2624.                 y1 = node->box.y + node->box.height;
  2625.                 if ((y0 < y_max) && (y1 >= y)) {
  2626.                         update = NULL;
  2627.                         if (node->expanded) {
  2628.                                 for (element = &node->data; element != NULL;
  2629.                                      element = element->next) {
  2630.                                         y0 = element->box.y;
  2631.                                         y1 = element->box.y +
  2632.                                                 element->box.height;
  2633.                                         if ((y0 < y_max) && (y1 >= y)) {
  2634.                                                 update = element->parent;
  2635.                                                 break;
  2636.                                         }
  2637.                                 }
  2638.                         } else {
  2639.                                 y0 = node->data.box.y;
  2640.                                 y1 = node->data.box.y + node->data.box.height;
  2641.                                 if ((y0 < y_max) && (y1 >= y))
  2642.                                         update = node->data.parent;
  2643.                         }
  2644.                         if ((update) && (node != tree->root)) {
  2645.                                 if (invert) {
  2646.                                         node->selected = !node->selected;
  2647.                                         tree_handle_node_element_changed(tree,
  2648.                                                         &node->data, false);
  2649.                                 } else if (!node->selected) {
  2650.                                         node->selected = true;
  2651.                                         tree_handle_node_element_changed(tree,
  2652.                                                         &node->data, false);
  2653.                                 }
  2654.                         }
  2655.                 }
  2656.                 if ((node->child != NULL) && (node->expanded))
  2657.                         tree_handle_selection_area_node(tree, node->child, y,
  2658.                                                         height, invert);
  2659.         }
  2660. }
  2661.  
  2662.  
  2663. /**
  2664.  * Updates the selected state for a region of nodes.
  2665.  *
  2666.  * \param tree    the tree to update
  2667.  * \param y       the minimum y of the selection rectangle
  2668.  * \param height  the height of the selection rectangle
  2669.  * \param invert  whether to invert the selected state
  2670.  */
  2671. static void tree_handle_selection_area(struct tree *tree, int y, int height,
  2672.                 bool invert)
  2673. {
  2674.         assert(tree != NULL);
  2675.         assert(tree->root != NULL);
  2676.  
  2677.         if (tree->root->child == NULL)
  2678.                 return;
  2679.  
  2680.         if (height < 0) {
  2681.                 y += height;
  2682.                 height = -height;
  2683.         }
  2684.         tree_handle_selection_area_node(tree, tree->root->child, y, height,
  2685.                         invert);
  2686. }
  2687.  
  2688.  
  2689. /**
  2690.  * Clears the processing flag.
  2691.  *
  2692.  * \param node    the node to process siblings and children of
  2693.  */
  2694. static void tree_clear_processing(struct node *node)
  2695. {
  2696.         for (; node != NULL; node = node->next) {
  2697.                 node->processing = false;
  2698.                 if (node->child != NULL)
  2699.                         tree_clear_processing(node->child);
  2700.         }
  2701. }
  2702.  
  2703.  
  2704. /**
  2705.  * Sets the processing flag to the selection state.
  2706.  *
  2707.  * \param node    the node to process siblings and children of
  2708.  */
  2709. static void tree_selected_to_processing(struct node *node)
  2710. {
  2711.         for (; node != NULL; node = node->next) {
  2712.                 node->processing = node->selected;
  2713.                 if ((node->child != NULL) && (node->expanded))
  2714.                         tree_selected_to_processing(node->child);
  2715.         }
  2716. }
  2717.  
  2718.  
  2719. /**
  2720.  * Moves the first node in a tree with the processing flag set.
  2721.  *
  2722.  * \param tree    the tree in which the move takes place
  2723.  * \param node    the node to move siblings/children of
  2724.  * \param link    the node to link before/as a child (folders) or before/after
  2725.  *                (link)
  2726.  * \param before  whether to link siblings before or after the supplied node
  2727.  * \param first   whether to always link after the supplied node (ie not
  2728.  *                inside of folders)
  2729.  * \return        the node moved
  2730.  */
  2731. static struct node *tree_move_processing_node(struct tree *tree,
  2732.                 struct node *node, struct node *link, bool before, bool first)
  2733. {
  2734.         struct node *result;
  2735.  
  2736.         bool folder = link->folder;
  2737.         for (; node != NULL; node = node->next) {
  2738.                 if (node->processing) {
  2739.                         node->processing = false;
  2740.                         tree_delink_node(tree, node);
  2741.                         if (!first)
  2742.                                 link->folder = false;
  2743.                         tree_link_node(tree, link, node, before);
  2744.                         if (!first)
  2745.                                 link->folder = folder;
  2746.                         return node;
  2747.                 }
  2748.                 if (node->child != NULL) {
  2749.                         result = tree_move_processing_node(tree, node->child,
  2750.                                                            link, before, first);
  2751.                         if (result != NULL)
  2752.                                 return result;
  2753.                 }
  2754.         }
  2755.         return NULL;
  2756. }
  2757.  
  2758.  
  2759. /**
  2760.  * Moves nodes within a tree.
  2761.  *
  2762.  * \param tree         the tree to process
  2763.  * \param destination  the node to link before/as a child (folders)
  2764.  *                     or before/after (link)
  2765.  * \param before       whether to link siblings before or after the supplied
  2766.  *                     node
  2767.  */
  2768. static void tree_move_selected_nodes(struct tree *tree,
  2769.                 struct node *destination, bool before)
  2770. {
  2771.         struct node *link;
  2772.         struct node *test;
  2773.         bool error;
  2774.  
  2775.         tree_clear_processing(tree->root);
  2776.         tree_selected_to_processing(tree->root);
  2777.  
  2778.         /* the destination node cannot be a child of any node with
  2779.            the processing flag set */
  2780.         error = destination->processing;
  2781.         for (test = destination; test != NULL; test = test->parent)
  2782.                 error |= test->processing;
  2783.         if (error) {
  2784.                 tree_clear_processing(tree->root);
  2785.                 return;
  2786.         }
  2787.         if ((destination->folder) && (!destination->expanded) && (!before)) {
  2788.                 tree_set_node_expanded(tree, destination, true, false, false);
  2789.         }
  2790.         link = tree_move_processing_node(tree, tree->root, destination, before,
  2791.                                          true);
  2792.         while (link != NULL)
  2793.                 link = tree_move_processing_node(tree, tree->root, link, false,
  2794.                                                  false);
  2795.  
  2796.         tree_clear_processing(tree->root);
  2797.         tree_recalculate_node_positions(tree, tree->root);
  2798.         if (tree->redraw)
  2799.                 tree->callbacks->redraw_request(0, 0, tree->width, tree->height,
  2800.                                                 tree->client_data);
  2801. }
  2802.  
  2803.  
  2804. /**
  2805.  * Handle the end of a drag operation
  2806.  *
  2807.  * \param tree  the tree on which the drag was performed
  2808.  * \param mouse mouse state during drag end
  2809.  * \param x0    x coordinate of drag start
  2810.  * \param y0    y coordinate of drag start
  2811.  * \param x1    x coordinate of drag end
  2812.  * \param y1    y coordinate of drag end
  2813.  */
  2814. void tree_drag_end(struct tree *tree, browser_mouse_state mouse, int x0, int y0,
  2815.                 int x1, int y1)
  2816. {
  2817.  
  2818.         bool before;
  2819.         struct node *node;
  2820.         int x, y;
  2821.  
  2822.         switch (tree->drag) {
  2823.         case TREE_NO_DRAG:
  2824.         case TREE_UNKNOWN_DRAG:
  2825.                 break;
  2826.  
  2827.         case TREE_TEXTAREA_DRAG:
  2828.                 x = tree->editing->box.x;
  2829.                 y = tree->editing->box.y;
  2830.                 if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
  2831.                         x += NODE_INSTEP;
  2832.                 textarea_mouse_action(tree->textarea, BROWSER_MOUSE_HOVER,
  2833.                                 x1 - x, y1 - y);
  2834.                 break;
  2835.  
  2836.         case TREE_SELECT_DRAG:
  2837.                 tree_handle_selection_area(tree, y0, y1 - y0,
  2838.                                            (mouse | BROWSER_MOUSE_HOLDING_2));
  2839.                 break;
  2840.  
  2841.         case TREE_MOVE_DRAG:
  2842.                 if (!(tree->flags & TREE_MOVABLE))
  2843.                         return;
  2844.                 node = tree_get_link_details(tree, x1, y1, &before);
  2845.                 tree_move_selected_nodes(tree, node, before);
  2846.                 break;
  2847.         }
  2848.  
  2849.         tree->drag = TREE_NO_DRAG;
  2850. }
  2851.  
  2852.  
  2853. /**
  2854.  * Key press handling for a tree.
  2855.  *
  2856.  * \param tree  The tree which got the keypress
  2857.  * \param key   The ucs4 character codepoint
  2858.  * \return      true if the keypress is dealt with, false otherwise.
  2859.  */
  2860. bool tree_keypress(struct tree *tree, uint32_t key)
  2861. {
  2862.         if (tree->editing != NULL)
  2863.                 switch (key) {
  2864.                 case KEY_ESCAPE:
  2865.                         tree_stop_edit(tree, false);
  2866.                         return true;
  2867.                 case KEY_NL:
  2868.                 case KEY_CR:
  2869.                         tree_stop_edit(tree, true);
  2870.                         return true;
  2871.                 default:
  2872.                         return textarea_keypress(tree->textarea, key);
  2873.                 }
  2874.  
  2875.         return false;
  2876. }
  2877.  
  2878.  
  2879. /**
  2880.  * Alphabetical comparison function for nodes
  2881.  *
  2882.  * \param n1  first node to compare
  2883.  * \param n2  first node to compare
  2884.  * \return    0 if equal, greater then zero if n1 > n2,
  2885.  *            less then zero if n2 < n1
  2886.  */
  2887. int tree_alphabetical_sort(struct node *n1, struct node *n2)
  2888. {
  2889.         return strcmp(n1->data.text, n2->data.text);
  2890. }
  2891.  
  2892.  
  2893. /**
  2894.  * Redraw requests from the textarea are piped through this because we have to
  2895.  * check the redraw flag of the tree before requesting a redraw and change the
  2896.  * position to tree origin relative.
  2897.  */
  2898.  
  2899. static void tree_textarea_callback(void *data, struct textarea_msg *msg)
  2900. {
  2901.         struct tree *tree = data;
  2902.         int x, y;
  2903.  
  2904.         switch (msg->type) {
  2905.         case TEXTAREA_MSG_DRAG_REPORT:
  2906.                 if (msg->data.drag == TEXTAREA_DRAG_NONE) {
  2907.                         /* Textarea drag finished */
  2908.                         tree->drag = TREE_NO_DRAG;
  2909.                 } else {
  2910.                         /* Textarea drag started */
  2911.                         tree->drag = TREE_TEXTAREA_DRAG;
  2912.                 }
  2913.                 break;
  2914.  
  2915.         case TEXTAREA_MSG_REDRAW_REQUEST:
  2916.                 x = msg->data.redraw.x0 + tree->editing->box.x;
  2917.                 y = msg->data.redraw.y0 + tree->editing->box.y;
  2918.  
  2919.                 if (tree->editing->type == NODE_ELEMENT_TEXT_PLUS_ICON)
  2920.                         x += NODE_INSTEP;
  2921.  
  2922.                 /* Redraw the textarea */
  2923.                 if (tree->redraw)
  2924.                         tree->callbacks->redraw_request(x, y,
  2925.                                         msg->data.redraw.x1 -
  2926.                                                 msg->data.redraw.x0,
  2927.                                         msg->data.redraw.y1 -
  2928.                                                 msg->data.redraw.y0,
  2929.                                         tree->client_data);
  2930.                 break;
  2931.  
  2932.         default:
  2933.                 break;
  2934.         }
  2935. }
  2936.  
  2937.  
  2938. /**
  2939.  * Starts editing a node_element
  2940.  *
  2941.  * \param tree          The tree to which element belongs
  2942.  * \param element       The element to start being edited
  2943.  */
  2944. void tree_start_edit(struct tree *tree, struct node_element *element)
  2945. {
  2946.         struct node *parent;
  2947.         int width, height;
  2948.         textarea_setup ta_setup;
  2949.  
  2950.         assert(tree != NULL);
  2951.         assert(element != NULL);
  2952.  
  2953.         if (tree->editing != NULL)
  2954.                 tree_stop_edit(tree, true);
  2955.  
  2956.         parent = element->parent;
  2957.         if (&parent->data == element)
  2958.                 parent = parent->parent;
  2959.         for (; parent != NULL; parent = parent->parent) {
  2960.                 if (!parent->expanded) {
  2961.                         tree_set_node_expanded(tree, parent, true,
  2962.                                                false, false);
  2963.                 }
  2964.         }
  2965.  
  2966.         tree->editing = element;
  2967.         tree->callbacks->get_window_dimensions(&width, NULL, tree->client_data);
  2968.         width -= element->box.x;
  2969.         height = element->box.height;
  2970.         if (element->type == NODE_ELEMENT_TEXT_PLUS_ICON)
  2971.                 width -= NODE_INSTEP;
  2972.  
  2973.         tree->ta_height = height;
  2974.  
  2975.         ta_setup.flags = TEXTAREA_INTERNAL_CARET;
  2976.         ta_setup.width = width;
  2977.         ta_setup.height = tree->ta_height;
  2978.         ta_setup.pad_top = 0;
  2979.         ta_setup.pad_right = 4;
  2980.         ta_setup.pad_bottom = 0;
  2981.         ta_setup.pad_left = 4;
  2982.         ta_setup.border_width = 1;
  2983.         ta_setup.border_col = 0x000000;
  2984.         ta_setup.selected_text = 0xffffff;
  2985.         ta_setup.selected_bg = 0x000000;
  2986.         ta_setup.text = plot_fstyle;
  2987.         ta_setup.text.foreground = 0x000000;
  2988.         ta_setup.text.background = 0xffffff;
  2989.  
  2990.         tree->textarea = textarea_create(&ta_setup,
  2991.                         tree_textarea_callback, tree);
  2992.         if (tree->textarea == NULL) {
  2993.                 tree_stop_edit(tree, false);
  2994.                 return;
  2995.         }
  2996.         textarea_set_text(tree->textarea, element->text);
  2997.  
  2998.         tree_handle_node_element_changed(tree, element, true);
  2999.         tree_recalculate_size(tree);
  3000.         tree->callbacks->scroll_visible(element->box.y, element->box.height,
  3001.                                         tree->client_data);
  3002. }
  3003.  
  3004.  
  3005. /**
  3006.  * Callback for fetchcache(). Should be removed once bitmaps get loaded directly
  3007.  * from disc
  3008.  */
  3009. static nserror tree_icon_callback(hlcache_handle *handle,
  3010.                 const hlcache_event *event, void *pw)
  3011. {
  3012.         return NSERROR_OK;
  3013. }
  3014.  
  3015.  
  3016. /**
  3017.  * Tree utility function. Placed here so that this code doesn't have to be
  3018.  * copied by each user.
  3019.  *
  3020.  * \param name  the name of the loaded icon, if it's not a full path the icon is
  3021.  *              looked for in the directory specified by tree_icons_dir
  3022.  * \return the icon in form of a content or NULL on failure
  3023.  */
  3024. hlcache_handle *tree_load_icon(const char *name)
  3025. {
  3026.         char *url = NULL;
  3027.         const char *icon_url = NULL;
  3028.         int len;
  3029.         hlcache_handle *c;
  3030.         nserror err;
  3031.         nsurl *icon_nsurl;
  3032.  
  3033.         /** @todo something like bitmap_from_disc is needed here */
  3034.  
  3035.         if (!strncmp(name, "file://", 7)) {
  3036.                 icon_url = name;
  3037.         } else {
  3038.                 char *native_path;
  3039.  
  3040.                 if (tree_icons_dir == NULL)
  3041.                         return NULL;
  3042.  
  3043.                 /* path + separator + leafname + '\0' */
  3044.                 len = strlen(tree_icons_dir) + 1 + strlen(name) + 1;
  3045.                 native_path = malloc(len);
  3046.                 if (native_path == NULL) {
  3047.                         LOG(("malloc failed"));
  3048.                         warn_user("NoMemory", 0);
  3049.                         return NULL;
  3050.                 }
  3051.  
  3052.                 /* Build native path */
  3053.                 memcpy(native_path, tree_icons_dir,
  3054.                        strlen(tree_icons_dir) + 1);
  3055.                 path_add_part(native_path, len, name);
  3056.  
  3057.                 /* Convert native path to URL */
  3058.                 url = path_to_url(native_path);
  3059.  
  3060.                 free(native_path);
  3061.                 icon_url = url;
  3062.         }
  3063.  
  3064.         err = nsurl_create(icon_url, &icon_nsurl);
  3065.         if (err != NSERROR_OK) {
  3066.                 if (url != NULL)
  3067.                         free(url);
  3068.                 return NULL;
  3069.         }
  3070.  
  3071.         /* Fetch the icon */
  3072.         err = hlcache_handle_retrieve(icon_nsurl, 0, 0, 0,
  3073.                                       tree_icon_callback, 0, 0,
  3074.                                       CONTENT_IMAGE, &c);
  3075.  
  3076.         nsurl_unref(icon_nsurl);
  3077.  
  3078.         /* If we built the URL here, free it */
  3079.         if (url != NULL)
  3080.                 free(url);
  3081.  
  3082.         if (err != NSERROR_OK) {
  3083.                 return NULL;
  3084.         }
  3085.  
  3086.         return c;
  3087. }
  3088.