texinfo-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[no subject]


From: Patrice Dumas
Date: Sat, 9 Mar 2024 17:52:47 -0500 (EST)

branch: master
commit 2cce537c6b7bccd30a65d266649e58be4dfbb54d
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Sat Mar 9 14:22:35 2024 +0100

    Set document->modified_information when modified, unset when passed to
    Perl
    
    * tp/Texinfo/XS/main/DocumentXS.xs (set_document_global_info),
    tp/Texinfo/XS/main/build_perl_info.c (get_document, fill_document_hv),
    tp/Texinfo/XS/main/document.c, tp/Texinfo/XS/main/output_unit.c
    (split_by_node, split_by_section, unsplit),
    tp/Texinfo/XS/main/targets.c (add_element_to_identifiers_target),
    tp/Texinfo/XS/structuring_transfo/StructuringTransfoXS.xs,
    tp/Texinfo/XS/structuring_transfo/structuring.c,
    tp/Texinfo/XS/structuring_transfo/transformations.c: set
    document->modified_information flags when set or modified in C;
    Remove the flags when passed to Perl document structure.
---
 ChangeLog                                          | 16 ++++++++
 tp/TODO                                            |  2 +
 tp/Texinfo/XS/main/DocumentXS.xs                   |  2 +
 tp/Texinfo/XS/main/build_perl_info.c               | 25 +++++++++++--
 tp/Texinfo/XS/main/document.c                      | 12 ++++++
 tp/Texinfo/XS/main/document_types.h                | 15 +++++++-
 tp/Texinfo/XS/main/output_unit.c                   | 16 ++++++--
 tp/Texinfo/XS/main/output_unit.h                   |  6 +--
 tp/Texinfo/XS/main/targets.c                       |  2 +
 .../XS/structuring_transfo/StructuringTransfoXS.xs | 43 ++++++++++++++++++----
 tp/Texinfo/XS/structuring_transfo/structuring.c    | 14 ++++++-
 .../XS/structuring_transfo/transformations.c       | 21 ++++++++---
 12 files changed, 150 insertions(+), 24 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index baf5e6a2ad..9aed887e5e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2024-03-09  Patrice Dumas  <pertusus@free.fr>
+
+       Set document->modified_information when modified, unset when passed to
+       Perl
+
+       * tp/Texinfo/XS/main/DocumentXS.xs (set_document_global_info),
+       tp/Texinfo/XS/main/build_perl_info.c (get_document, fill_document_hv),
+       tp/Texinfo/XS/main/document.c, tp/Texinfo/XS/main/output_unit.c
+       (split_by_node, split_by_section, unsplit),
+       tp/Texinfo/XS/main/targets.c (add_element_to_identifiers_target),
+       tp/Texinfo/XS/structuring_transfo/StructuringTransfoXS.xs,
+       tp/Texinfo/XS/structuring_transfo/structuring.c,
+       tp/Texinfo/XS/structuring_transfo/transformations.c: set
+       document->modified_information flags when set or modified in C;
+       Remove the flags when passed to Perl document structure.
+
 2024-03-08  Patrice Dumas  <pertusus@free.fr>
 
        * tp/Texinfo/Document.pm (indices_sort_strings),
diff --git a/tp/TODO b/tp/TODO
index 4e12814b06..9ea65e779d 100644
--- a/tp/TODO
+++ b/tp/TODO
@@ -24,6 +24,8 @@ Texinfo/ParserNonXS.pm
 handle on tree:
 t/test_utils.pl all over
 
+Check if LABEL identifier should be const
+
 Bugs
 ====
 
diff --git a/tp/Texinfo/XS/main/DocumentXS.xs b/tp/Texinfo/XS/main/DocumentXS.xs
index 288eb323a5..220254436c 100644
--- a/tp/Texinfo/XS/main/DocumentXS.xs
+++ b/tp/Texinfo/XS/main/DocumentXS.xs
@@ -153,6 +153,8 @@ set_document_global_info (SV *document_in, char *key, SV 
*value_sv)
         document = get_sv_document_document (document_in, 0);
         if (document)
           {
+            document->modified_information |= F_DOCM_global_info;
+
             if (!strcmp (key, "input_file_name"))
               {
                 char *value = (char *)SvPVbyte_nolen(value_sv);
diff --git a/tp/Texinfo/XS/main/build_perl_info.c 
b/tp/Texinfo/XS/main/build_perl_info.c
index 33f55d1481..c196e08844 100644
--- a/tp/Texinfo/XS/main/build_perl_info.c
+++ b/tp/Texinfo/XS/main/build_perl_info.c
@@ -1373,6 +1373,8 @@ get_document (size_t document_descriptor)
 #define STORE(key, value) hv_store (hv, key, strlen (key), newRV_inc ((SV *) 
value), 0)
   STORE("tree", hv_tree);
   STORE("global_info", hv_info);
+
+  document->modified_information &= ~F_DOCM_global_info;
 #undef STORE
 
   hv_store (hv, "document_descriptor", strlen ("document_descriptor"),
@@ -1451,22 +1453,39 @@ fill_document_hv (HV *hv, size_t document_descriptor, 
int no_store)
 
   /* must be kept in sync with Texinfo::Document register keys */
   STORE("tree", hv_tree);
+  document->modified_information &= ~F_DOCM_tree;
   STORE("indices", hv_index_names);
+  document->modified_information &= ~F_DOCM_index_names;
   STORE("listoffloats_list", hv_listoffloats_list);
+  document->modified_information &= ~F_DOCM_floats;
   STORE("internal_references", av_internal_xref);
+  document->modified_information &= ~F_DOCM_internal_references;
   STORE("commands_info", hv_commands_info);
+  document->modified_information &= ~F_DOCM_global_commands;
   STORE("global_info", hv_info);
+  document->modified_information &= ~F_DOCM_global_info;
   STORE("identifiers_target", hv_identifiers_target);
+  document->modified_information &= ~F_DOCM_identifiers_target;
   STORE("labels_list", av_labels_list);
+  document->modified_information &= ~F_DOCM_labels_list;
 
   if (av_nodes_list)
-    STORE("nodes_list", av_nodes_list);
+    {
+      STORE("nodes_list", av_nodes_list);
+      document->modified_information &= ~F_DOCM_nodes_list;
+    }
 
   if (av_sections_list)
-    STORE("sections_list", av_sections_list);
+    {
+      STORE("sections_list", av_sections_list);
+      document->modified_information &= ~F_DOCM_sections_list;
+    }
 
   if (hv_indices_sort_strings)
-    STORE("index_entries_sort_strings", hv_indices_sort_strings);
+    {
+      STORE("index_entries_sort_strings", hv_indices_sort_strings);
+      document->modified_information &= ~F_DOCM_indices_sort_strings;
+    }
 #undef STORE
 
   if (no_store)
diff --git a/tp/Texinfo/XS/main/document.c b/tp/Texinfo/XS/main/document.c
index c01fad6885..04965824a8 100644
--- a/tp/Texinfo/XS/main/document.c
+++ b/tp/Texinfo/XS/main/document.c
@@ -110,6 +110,11 @@ register_document (ELEMENT *root, INDEX **index_names,
 
   document->listoffloats = float_list_to_listoffloats_list (floats_list);
 
+  document->modified_information |= F_DOCM_tree | F_DOCM_index_names
+     | F_DOCM_floats | F_DOCM_internal_references | F_DOCM_labels_list
+     | F_DOCM_identifiers_target | F_DOCM_global_info
+     | F_DOCM_global_commands;
+
   /*
   fprintf(stderr, "REGISTER %zu %p %p %p %p\n", document_index +1, document,
                        document->tree, document->index_names, 
document->options);
@@ -121,6 +126,7 @@ void
 register_document_nodes_list (DOCUMENT *document, ELEMENT_LIST *nodes_list)
 {
   document->nodes_list = nodes_list;
+  document->modified_information |= F_DOCM_nodes_list;
 }
 
 void
@@ -128,6 +134,7 @@ register_document_sections_list (DOCUMENT *document,
                                  ELEMENT_LIST *sections_list)
 {
   document->sections_list = sections_list;
+  document->modified_information |= F_DOCM_nodes_list;
 }
 
 void
@@ -144,6 +151,7 @@ document_merged_indices (DOCUMENT *document)
       if (!document->merged_indices)
         {
           document->merged_indices = merge_indices (document->index_names);
+          document->modified_information |= F_DOCM_merged_indices;
         }
     }
   return document->merged_indices;
@@ -285,6 +293,8 @@ sorted_indices_by_index (DOCUMENT *document,
         = sort_indices_by_index (document, error_messages, options,
                                  use_unicode_collation, collation_language,
                                  collation_locale);
+      /* TODO keep track of the precise sorted index that was modified */
+      document->modified_information |= F_DOCM_sorted_indices_by_index;
     }
   return collation_sorted_indices->sorted_indices;
 }
@@ -396,6 +406,8 @@ sorted_indices_by_letter (DOCUMENT *document,
         = sort_indices_by_letter (document, error_messages, options,
                                   use_unicode_collation, collation_language,
                                   collation_locale);
+      /* TODO keep track of the precise sorted index that was modified */
+      document->modified_information |= F_DOCM_sorted_indices_by_letter;
     }
   return collation_sorted_indices->sorted_indices;
 }
diff --git a/tp/Texinfo/XS/main/document_types.h 
b/tp/Texinfo/XS/main/document_types.h
index ef24acaab9..2817aff9cb 100644
--- a/tp/Texinfo/XS/main/document_types.h
+++ b/tp/Texinfo/XS/main/document_types.h
@@ -32,7 +32,20 @@ struct OPTIONS;
 /* same with convert_to_text.h */
 struct TEXT_OPTIONS;
 
-#define F_DOCM_indices_sort_strings      0x0001
+#define F_DOCM_tree                      0x0001
+#define F_DOCM_index_names               0x0002
+#define F_DOCM_floats                    0x0004
+#define F_DOCM_internal_references       0x0008
+#define F_DOCM_labels_list               0x0010
+#define F_DOCM_identifiers_target        0x0020
+#define F_DOCM_global_info               0x0040
+#define F_DOCM_global_commands           0x0080
+#define F_DOCM_nodes_list                0x0100
+#define F_DOCM_sections_list             0x0200
+#define F_DOCM_merged_indices            0x0400
+#define F_DOCM_indices_sort_strings      0x0800
+#define F_DOCM_sorted_indices_by_index   0x1000
+#define F_DOCM_sorted_indices_by_letter  0x2000
 
 enum error_type { MSG_error, MSG_warning,
                   MSG_document_error, MSG_document_warning };
diff --git a/tp/Texinfo/XS/main/output_unit.c b/tp/Texinfo/XS/main/output_unit.c
index a1f116c6b2..024fecc905 100644
--- a/tp/Texinfo/XS/main/output_unit.c
+++ b/tp/Texinfo/XS/main/output_unit.c
@@ -136,7 +136,7 @@ add_to_output_unit_list (OUTPUT_UNIT_LIST *list, 
OUTPUT_UNIT *output_unit)
 
 /* in addition to splitting, register the output_units list */
 int
-split_by_node (const DOCUMENT *document)
+split_by_node (DOCUMENT *document)
 {
   const ELEMENT *root = document->tree;
   int output_units_descriptor = new_output_units_descriptor ();
@@ -148,6 +148,9 @@ split_by_node (const DOCUMENT *document)
 
   add_to_output_unit_list (output_units, current);
 
+  if (root->contents.number > 0)
+    document->modified_information |= F_DOCM_tree;
+
   for (i = 0; i < root->contents.number; i++)
     {
       ELEMENT *content = root->contents.list[i];
@@ -206,7 +209,7 @@ split_by_node (const DOCUMENT *document)
 
 /* in addition to splitting, register the output_units list */
 int
-split_by_section (const DOCUMENT *document)
+split_by_section (DOCUMENT *document)
 {
   const ELEMENT *root = document->tree;
   int output_units_descriptor = new_output_units_descriptor ();
@@ -215,6 +218,9 @@ split_by_section (const DOCUMENT *document)
   OUTPUT_UNIT *current = new_output_unit (OU_unit);
   int i;
 
+  if (root->contents.number > 0)
+    document->modified_information |= F_DOCM_tree;
+
   add_to_output_unit_list (output_units, current);
 
   for (i = 0; i < root->contents.number; i++)
@@ -266,7 +272,7 @@ split_by_section (const DOCUMENT *document)
 }
 
 int
-unsplit (const DOCUMENT *document)
+unsplit (DOCUMENT *document)
 {
   const ELEMENT *root = document->tree;
   int unsplit_needed = 0;
@@ -284,6 +290,10 @@ unsplit (const DOCUMENT *document)
           unsplit_needed = 1;
         }
     }
+
+  if (unsplit_needed)
+    document->modified_information |= F_DOCM_tree;
+
   return unsplit_needed;
 }
 
diff --git a/tp/Texinfo/XS/main/output_unit.h b/tp/Texinfo/XS/main/output_unit.h
index f91be65e95..355adda6b6 100644
--- a/tp/Texinfo/XS/main/output_unit.h
+++ b/tp/Texinfo/XS/main/output_unit.h
@@ -11,9 +11,9 @@ extern const char *relative_unit_direction_name[];
 OUTPUT_UNIT_LIST *retrieve_output_units (int output_units_descriptor);
 size_t new_output_units_descriptor (void);
 
-int split_by_node (const DOCUMENT *document);
-int split_by_section (const DOCUMENT *document);
-int unsplit (const DOCUMENT *document);
+int split_by_node (DOCUMENT *document);
+int split_by_section (DOCUMENT *document);
+int unsplit (DOCUMENT *document);
 void split_pages (OUTPUT_UNIT_LIST *output_units, const char *split);
 
 OUTPUT_UNIT *new_output_unit (enum output_unit_type unit_type);
diff --git a/tp/Texinfo/XS/main/targets.c b/tp/Texinfo/XS/main/targets.c
index 5f5dc7351c..202d85f7f8 100644
--- a/tp/Texinfo/XS/main/targets.c
+++ b/tp/Texinfo/XS/main/targets.c
@@ -234,6 +234,8 @@ add_element_to_identifiers_target (DOCUMENT *document, 
ELEMENT *element,
           destroy_label_list (identifiers_target);
           document->identifiers_target = sorted_identifiers_target;
           *status = 0;
+          document->modified_information |= F_DOCM_labels_list
+                                   | F_DOCM_identifiers_target;
           return normalized;
         }
       *status = 1;
diff --git a/tp/Texinfo/XS/structuring_transfo/StructuringTransfoXS.xs 
b/tp/Texinfo/XS/structuring_transfo/StructuringTransfoXS.xs
index 9239a48005..e8b4faa5f6 100644
--- a/tp/Texinfo/XS/structuring_transfo/StructuringTransfoXS.xs
+++ b/tp/Texinfo/XS/structuring_transfo/StructuringTransfoXS.xs
@@ -69,6 +69,8 @@ fill_gaps_in_sectioning (SV *tree_in, ...)
               }
             added_sections = fill_gaps_in_sectioning (document->tree,
                                                    commands_heading_content);
+            if (added_sections && added_sections->number > 0)
+              document->modified_information |= F_DOCM_tree;
             /* cannot easily be used as it does not match with perl tree.
                Also the return would not be usable as error status */
             destroy_list (added_sections);
@@ -118,8 +120,12 @@ relate_index_entries_to_table_items_in_tree (SV 
*document_in)
                                           document->descriptor);
               }
             else
-              relate_index_entries_to_table_items_in_tree (document->tree,
+              {
+                relate_index_entries_to_table_items_in_tree (document->tree,
                                                       document->index_names);
+                document->modified_information |= F_DOCM_tree
+                                                 | F_DOCM_index_names;
+              }
           }
 
 void
@@ -130,7 +136,10 @@ move_index_entries_after_items_in_tree (SV *tree_in)
         document = get_sv_tree_document (tree_in,
                                         
"move_index_entries_after_items_in_tree");
         if (document)
-          move_index_entries_after_items_in_tree (document->tree);
+          {
+            move_index_entries_after_items_in_tree (document->tree);
+            document->modified_information |= F_DOCM_tree;
+          }
 
 # The perl function returns a tree, as the
 # argument could be modified.  Here, tree_in is always a container
@@ -238,7 +247,10 @@ complete_tree_nodes_menus (SV *tree_in, SV 
*use_sections_in=0)
             use_sections = SvIV (use_sections_in);
           }
         if (document)
-          complete_tree_nodes_menus (document->tree, use_sections);
+          {
+            complete_tree_nodes_menus (document->tree, use_sections);
+            document->modified_information |= F_DOCM_tree;
+          }
 
 # We use the options of the document, so we ignore
 # customization_information, which should contain the same information
@@ -318,7 +330,10 @@ protect_colon_in_tree (SV *tree_in)
         document = get_sv_tree_document (tree_in, "protect_colon_in_tree");
         /* there is no need to replace the root of the tree */
         if (document)
-          protect_colon_in_tree (document->tree);
+          {
+            protect_colon_in_tree (document->tree);
+            document->modified_information |= F_DOCM_tree;
+          }
 
 void
 protect_comma_in_tree (SV *tree_in)
@@ -328,7 +343,10 @@ protect_comma_in_tree (SV *tree_in)
         document = get_sv_tree_document (tree_in, "protect_comma_in_tree");
         /* there is no need to replace the root of the tree */
         if (document)
-          protect_comma_in_tree (document->tree);
+          {
+            protect_comma_in_tree (document->tree);
+            document->modified_information |= F_DOCM_tree;
+          }
 
 void
 protect_node_after_label_in_tree (SV *tree_in)
@@ -339,7 +357,10 @@ protect_node_after_label_in_tree (SV *tree_in)
                               "protect_node_after_label_in_tree");
         /* there is no need to replace the root of the tree */
         if (document)
-          protect_node_after_label_in_tree (document->tree);
+          {
+            protect_node_after_label_in_tree (document->tree);
+            document->modified_information |= F_DOCM_tree;
+          }
 
 void
 protect_hashchar_at_line_beginning (SV *tree_in, ...)
@@ -351,7 +372,10 @@ protect_hashchar_at_line_beginning (SV *tree_in, ...)
                                          "protect_hashchar_at_line_beginning");
         /* there is no need to replace the root of the tree */
         if (document)
-          protect_hashchar_at_line_beginning (document);
+          {
+            protect_hashchar_at_line_beginning (document);
+            document->modified_information |= F_DOCM_tree;
+          }
 
 void
 protect_first_parenthesis_in_targets (SV *tree_in)
@@ -361,7 +385,10 @@ protect_first_parenthesis_in_targets (SV *tree_in)
         document = get_sv_tree_document (tree_in,
                               "protect_first_parenthesis_in_targets");
         if (document)
-          protect_first_parenthesis_in_targets (document->tree);
+          {
+            protect_first_parenthesis_in_targets (document->tree);
+            document->modified_information |= F_DOCM_tree;
+          }
 
 SV *
 split_by_node (SV *document_in)
diff --git a/tp/Texinfo/XS/structuring_transfo/structuring.c 
b/tp/Texinfo/XS/structuring_transfo/structuring.c
index 8f662284c5..9d830583cd 100644
--- a/tp/Texinfo/XS/structuring_transfo/structuring.c
+++ b/tp/Texinfo/XS/structuring_transfo/structuring.c
@@ -106,6 +106,8 @@ sectioning_structure (DOCUMENT *document)
           || content->cmd == CM_bye)
         continue;
 
+      document->modified_information |= F_DOCM_tree;
+
       add_to_element_list (sections_list, content);
 
       if (content->cmd == CM_top && !section_top)
@@ -831,6 +833,8 @@ set_menus_node_directions (DOCUMENT *document)
       if (!menus)
         continue;
 
+      document->modified_information |= F_DOCM_tree;
+
       if (menus->number > 1)
         {
           for (j = 1; j < menus->number; j++)
@@ -1001,6 +1005,8 @@ complete_node_tree_with_menus (DOCUMENT *document)
   if (!nodes_list || nodes_list->number <= 0)
     return;
 
+  document->modified_information |= F_DOCM_tree;
+
   /* Go through all the nodes */
 
   for (i = 0; i < nodes_list->number; i++)
@@ -1324,6 +1330,8 @@ nodes_tree (DOCUMENT *document)
       if (!normalized)
         continue;
 
+      document->modified_information |= F_DOCM_tree;
+
       add_to_element_list (nodes_list, node);
       is_target = lookup_extra_integer (node, "is_target", &status);
       if (is_target && !strcmp (normalized, "Top"))
@@ -1499,6 +1507,8 @@ associate_internal_references (DOCUMENT *document)
   if (!refs || !refs->number)
     return;
 
+  document->modified_information |= F_DOCM_tree;
+
   for (i = 0; i < refs->number; i++)
     {
       ELEMENT *ref = refs->list[i];
@@ -1590,6 +1600,8 @@ number_floats (DOCUMENT *document)
   if (!listoffloats_list)
     return;
 
+  document->modified_information |= F_DOCM_tree;
+
   for (i = 0; i < listoffloats_list->number; i++)
     {
       const LISTOFFLOATS_TYPE *listoffloats
@@ -1845,7 +1857,7 @@ new_complete_node_menu (const ELEMENT *node, DOCUMENT 
*document,
 
   if (section && section->cmd == CM_top && options)
     {
-      char *normalized = lookup_extra_string (node, "normalized");
+      const char *normalized = lookup_extra_string (node, "normalized");
       if (normalized && !strcmp (normalized, "Top"))
         {
           int content_index = 0;
diff --git a/tp/Texinfo/XS/structuring_transfo/transformations.c 
b/tp/Texinfo/XS/structuring_transfo/transformations.c
index 3d220992cc..1632220518 100644
--- a/tp/Texinfo/XS/structuring_transfo/transformations.c
+++ b/tp/Texinfo/XS/structuring_transfo/transformations.c
@@ -771,12 +771,15 @@ insert_nodes_for_sectioning_commands (DOCUMENT *document)
       if (data_cmd && data_cmd != CM_node && data_cmd != CM_part
           && flags & CF_root)
         {
-          ELEMENT *associated_node = lookup_extra_element (content,
-                                                 "associated_node");
+          const ELEMENT *associated_node = lookup_extra_element (content,
+                                                       "associated_node");
           if (!associated_node)
             {
               ELEMENT *added_node;
               ELEMENT *new_node_tree;
+
+              document->modified_information |= F_DOCM_tree;
+
               if (content->cmd == CM_top)
                 {
                   ELEMENT *top_node_text = new_element (ET_NONE);
@@ -885,7 +888,10 @@ reference_to_arg_internal (const char *type,
           && document->internal_references->number > 0)
         {
           remove_element_from_list (document->internal_references, e);
+          document->modified_information |= F_DOCM_labels_list;
         }
+      if (document)
+        document->modified_information |= F_DOCM_tree;
       destroy_element_and_children (e);
       if (new->contents.number == 0)
         text_append (&new->text, "");
@@ -902,7 +908,7 @@ reference_to_arg_in_tree (ELEMENT *tree, DOCUMENT *document)
 }
 
 void
-prepend_new_menu_in_node_section (ELEMENT * node, ELEMENT *section,
+prepend_new_menu_in_node_section (ELEMENT *node, ELEMENT *section,
                                   ELEMENT *current_menu)
 {
   ELEMENT *empty_line = new_element (ET_empty_line);
@@ -1114,7 +1120,10 @@ complete_tree_nodes_missing_menu (const ELEMENT *root, 
DOCUMENT *document,
           ELEMENT *current_menu = new_complete_node_menu (node, document,
                                                       options, use_sections);
           if (current_menu)
-            prepend_new_menu_in_node_section (node, section, current_menu);
+            {
+              prepend_new_menu_in_node_section (node, section, current_menu);
+              document->modified_information |= F_DOCM_tree;
+            }
         }
     }
   destroy_list (non_automatic_nodes);
@@ -1154,6 +1163,8 @@ regenerate_master_menu (DOCUMENT *document, int 
use_sections)
   if (!master_menu)
     return 0;
 
+  document->modified_information |= F_DOCM_tree;
+
   for (i = 0; i < menus->number; i++)
     {
       int detailmenu_index = 0;
@@ -1194,7 +1205,7 @@ regenerate_master_menu (DOCUMENT *document, int 
use_sections)
                                   char *removed_internal_texi
                                      = convert_to_texinfo (entry_content);
                                   fprintf (stderr,
-                                    "BUG: %s: not found in internal refs\n", 
+                                    "BUG: %s: not found in internal refs\n",
                                       removed_internal_texi);
                                   free (removed_internal_texi);
                                 }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]