summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikael Hallendal <micke@codefactory.se>2002-05-26 22:17:26 +0000
committerMikael Hallendal <hallski@src.gnome.org>2002-05-26 22:17:26 +0000
commitd06b4d042f0ab772d2794f4cad8b4f553de2d478 (patch)
treeeb043da03905c598bee45bbd16f0f5fdb500cc8d
parentedcd6250babb9d72aaa958dca73909c5de0c9059 (diff)
downloadyelp-d06b4d042f0ab772d2794f4cad8b4f553de2d478.tar.gz
added, used to get a chunk from a multi chunked document.
2002-05-27 Mikael Hallendal <micke@codefactory.se> * src/yelp-reader.c: (reader_get_chunk): added, used to get a chunk from a multi chunked document. (reader_man_info_start): - now handles docbook too. will be renamed later. - add docbook results in cache. - get chunk from document if docbook. (yelp_reader_start): - check in cache if document is there, if so, just get the chunk and signal. - if not in cache, use g_timeout_add instead of idle. * src/yelp-db2html.c: - this is now it's own binary - use multichunk - don't use YelpURI so that we don't need to init gnome vfs * src/yelp-db2html.h: removed * src/yelp-cache.c: first dummy implementation of cache. * src/yelp-base.c (yelp_base_init): init the cache. * src/Makefile.am: (yelp_db2html_LDADD): added binary for db2html. (yelp_SOURCES): added yelp-cache.[ch] and removed yelp-db2html.[ch]
-rw-r--r--ChangeLog30
-rw-r--r--src/.cvsignore1
-rw-r--r--src/Makefile.am12
-rw-r--r--src/yelp-base.c4
-rw-r--r--src/yelp-cache.c62
-rw-r--r--src/yelp-cache.h (renamed from src/yelp-db2html.h)21
-rw-r--r--src/yelp-db2html.c96
-rw-r--r--src/yelp-history.c1
-rw-r--r--src/yelp-reader.c177
9 files changed, 315 insertions, 89 deletions
diff --git a/ChangeLog b/ChangeLog
index 3823dd64..7626904a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2002-05-27 Mikael Hallendal <micke@codefactory.se>
+
+ * src/yelp-reader.c:
+ (reader_get_chunk): added, used to get a chunk from a multi
+ chunked document.
+ (reader_man_info_start):
+ - now handles docbook too. will be renamed later.
+ - add docbook results in cache.
+ - get chunk from document if docbook.
+ (yelp_reader_start):
+ - check in cache if document is there, if so, just get the chunk
+ and signal.
+ - if not in cache, use g_timeout_add instead of idle.
+
+ * src/yelp-db2html.c:
+ - this is now it's own binary
+ - use multichunk
+ - don't use YelpURI so that we don't need to init gnome vfs
+
+ * src/yelp-db2html.h: removed
+
+ * src/yelp-cache.c: first dummy implementation of cache.
+
+ * src/yelp-base.c (yelp_base_init): init the cache.
+
+ * src/Makefile.am:
+ (yelp_db2html_LDADD): added binary for db2html.
+ (yelp_SOURCES): added yelp-cache.[ch] and removed
+ yelp-db2html.[ch]
+
2002-05-26 Mikael Hallendal <micke@codefactory.se>
* stylesheets/yelp-customization.xsl:
diff --git a/src/.cvsignore b/src/.cvsignore
index dbea3feb..7ed37c19 100644
--- a/src/.cvsignore
+++ b/src/.cvsignore
@@ -15,4 +15,5 @@ test-reader
yelp-marshal.c
yelp-marshal.h
yelp
+yelp-db2html
core*
diff --git a/src/Makefile.am b/src/Makefile.am
index 7521b436..b3cf7816 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -15,7 +15,7 @@ else
html_widget_impl=yelp-html-gtkhtml2.c
endif
-bin_PROGRAMS = yelp
+bin_PROGRAMS = yelp yelp-db2html
noinst_PROGRAMS = test-uri test-reader
@@ -31,10 +31,10 @@ test_uri_LDADD = \
test_reader_SOURCES = \
test-reader.c \
yelp-uri.c yelp-uri.h \
+ yelp-cache.c yelp-cache.h \
yelp-reader.c yelp-reader.h \
yelp-error.c yelp-error.h \
yelp-util.c yelp-util.h \
- yelp-db2html.c yelp-db2html.h \
yelp-marshal-main.c
test_reader_LDADD = \
@@ -56,11 +56,17 @@ yelp-marshal.c: yelp-marshal.h
yelp-marshal-main.c: yelp-marshal.c
+yelp_db2html_SOURCES = \
+ yelp-db2html.c
+
+yelp_db2html_LDADD = \
+ @YELP_LIBS@
+
yelp_SOURCES = \
$(gnome_yelp_idl_sources) \
yelp-base.c yelp-base.h \
+ yelp-cache.c yelp-cache.h \
yelp-error.c yelp-error.h \
- yelp-db2html.c yelp-db2html.h \
yelp-history.c yelp-history.h \
$(html_widget_impl) yelp-html.h \
yelp-index-model.c yelp-index-model.h \
diff --git a/src/yelp-base.c b/src/yelp-base.c
index 8a557a7d..f236e75f 100644
--- a/src/yelp-base.c
+++ b/src/yelp-base.c
@@ -1,6 +1,6 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
- * Copyright (C) 2001 Mikael Hallendal <micke@codefactory.se>
+ * Copyright (C) 2001-2002 Mikael Hallendal <micke@codefactory.se>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -26,6 +26,7 @@
#include <string.h>
+#include "yelp-cache.h"
#include "yelp-window.h"
#include "yelp-section.h"
#include "yelp-scrollkeeper.h"
@@ -122,6 +123,7 @@ yelp_base_init (YelpBase *base)
priv->windows = NULL;
base->priv = priv;
+ yelp_cache_init ();
}
static void
diff --git a/src/yelp-cache.c b/src/yelp-cache.c
new file mode 100644
index 00000000..8511e154
--- /dev/null
+++ b/src/yelp-cache.c
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2002 Mikael Hallendal <micke@codefactory.se>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Mikael Hallendal <micke@codefactory.se>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include "yelp-cache.h"
+
+GHashTable *cache_table;
+GMutex *cache_mutex;
+
+void
+yelp_cache_init (void)
+{
+ cache_mutex = g_mutex_new ();
+ cache_table = g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+const gchar *
+yelp_cache_lookup (const gchar *path)
+{
+ const gchar *ret_val;
+
+ g_mutex_lock (cache_mutex);
+
+ ret_val = (const gchar *) g_hash_table_lookup (cache_table, path);
+
+ g_mutex_unlock (cache_mutex);
+
+ return ret_val;
+}
+
+void
+yelp_cache_add (const gchar *path, const gchar *html)
+{
+ g_mutex_lock (cache_mutex);
+
+ g_hash_table_insert (cache_table, (gchar *) path, g_strdup (html));
+
+ g_mutex_unlock (cache_mutex);
+}
diff --git a/src/yelp-db2html.h b/src/yelp-cache.h
index 32315ec9..d2bbb660 100644
--- a/src/yelp-db2html.h
+++ b/src/yelp-cache.h
@@ -20,22 +20,17 @@
* Author: Mikael Hallendal <micke@codefactory.se>
*/
-#ifndef __YELP_DB2HTML_H__
-#define __YELP_DB2HTML_H__
+#ifndef __YELP_CACHE_H__
+#define __YELP_CACHE_H__
#include <glib.h>
-#include <libxml/xmlversion.h>
-#include <libxml/xmlmemory.h>
-#include <libxml/debugXML.h>
-#include <libxml/HTMLtree.h>
-#include <libxml/DOCBparser.h>
-#include <libxml/catalog.h>
#include "yelp-uri.h"
-gboolean
-yelp_db2html_convert (YelpURI *uri,
- xmlOutputBufferPtr buf,
- GError **error);
+void yelp_cache_init (void);
-#endif /* __YELP_DB2HTML_H__ */
+const gchar * yelp_cache_lookup (const gchar *path);
+
+void yelp_cache_add (const gchar *path,
+ const gchar *html);
+#endif /* __YELP_CACHE_H__ */
diff --git a/src/yelp-db2html.c b/src/yelp-db2html.c
index b43ea417..cf4244ae 100644
--- a/src/yelp-db2html.c
+++ b/src/yelp-db2html.c
@@ -39,112 +39,92 @@
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
+#include <libgnomevfs/gnome-vfs-init.h>
#include "yelp-error.h"
#include "yelp-db2html.h"
-#define d(x)
-
/* stylesheet location based on Linux Standard Base *
* http://www.linuxbase.org/spec/gLSB/gLSB/sgmlr002.html */
#define STYLESHEET_PATH DATADIR"/sgml/docbook/yelp"
#define STYLESHEET STYLESHEET_PATH"/yelp-customization.xsl"
-gboolean
-yelp_db2html_convert (YelpURI *uri,
- xmlOutputBufferPtr buf,
- GError **error)
+gint
+main (gint argc, gchar **argv)
{
- static xsltStylesheetPtr stylesheet = NULL;
- xmlDocPtr db_doc;
- xmlDocPtr final_doc;
- const gchar *params[16 + 1];
- gchar *pathname;
- GTimer *timer;
+ xsltStylesheet *stylesheet = NULL;
+/* YelpURI *uri; */
+ xmlDocPtr db_doc;
+ xmlDocPtr final_doc;
+ const gchar *params[16 + 1];
+ gchar *pathname;
+ gchar *docpath;
- db_doc = NULL;
+ db_doc = NULL;
+
+ if (argc < 2) {
+ g_print ("Usage 'yelp-db2html url'\n");
+ exit (1);
+ }
- timer = g_timer_new ();
+ docpath = argv[1];
- d(g_print ("Convert file: %s\n", yelp_uri_get_path (uri)));
-
/* libxml housekeeping */
xmlSubstituteEntitiesDefault(1);
xmlLoadExtDtdDefaultValue = 1;
/* parse the stylesheet */
- if (!stylesheet) {
- stylesheet = xsltParseStylesheetFile (STYLESHEET);
- }
+ stylesheet = xsltParseStylesheetFile (STYLESHEET);
if (!stylesheet) {
- g_set_error (error,
- YELP_ERROR,
- YELP_ERROR_DOCBOOK_2_HTML,
- _("Error while parsing the stylesheet, make sure you have your docbook environment setup correctly."));
-
- /* FIXME: Set GError */
- return FALSE;
+ g_error ("Error while parsing the stylesheet, make sure you have your docbook environment setup correctly.");
+ exit (1);
}
- if (yelp_uri_get_type (uri) == YELP_URI_TYPE_DOCBOOK_XML) {
- db_doc = xmlParseFile (yelp_uri_get_path (uri));
+ if (strstr (docpath, ".sgml")) {
+ db_doc = docbParseFile (docpath, "UTF-8");
} else {
- db_doc = docbParseFile (yelp_uri_get_path (uri), "UTF-8");
+ db_doc = xmlParseFile (docpath);
}
if (db_doc == NULL) {
- /* FIXME: Set something in the GError */
- g_set_error (error,
- YELP_ERROR,
- YELP_ERROR_DOCBOOK_2_HTML,
- _("Couldn't parse the document '%s'."),
- yelp_uri_get_path (uri));
-
- return FALSE;
+ g_error ("Couldn't parse the document '%s'.",
+ docpath);
+ exit (1);
}
/* retrieve path component of filename passed in at
command line */
- pathname = g_path_get_dirname (yelp_uri_get_path (uri));
+ pathname = g_path_get_dirname (docpath);
/* set params to be passed to stylesheet */
params[0] = "gdb_docname";
- params[1] = g_strconcat("\"", yelp_uri_get_path (uri), "\"", NULL) ;
+ params[1] = g_strconcat("\"", docpath, "\"", NULL) ;
params[2] = "gdb_pathname";
params[3] = g_strconcat("\"", pathname, "\"", NULL) ;
params[4] = "gdb_stylesheet_path";
params[5] = STYLESHEET_PATH;
- params[6] = NULL;
+ params[6] = "gdb_multichunk";
+ params[7] = "1";
+ params[8] = NULL;
g_free (pathname);
- if (yelp_uri_get_section (uri)) {
- params[6] = "gdb_rootid";
- params[7] = g_strconcat("\"",
- yelp_uri_get_section (uri),
- "\"",
- NULL) ;
- params[8] = NULL;
- }
-
final_doc = xsltApplyStylesheet (stylesheet, db_doc, params);
xmlFree (db_doc);
if (!final_doc) {
- g_set_error (error,
- YELP_ERROR,
- YELP_ERROR_DOCBOOK_2_HTML,
- _("Error while applying the stylesheet."));
- return FALSE;
+ g_error ("Error while applying the stylesheet.");
+ exit (1);
}
- /* Output the results to the OutputBuffer */
- xsltSaveResultTo (buf, final_doc, stylesheet);
+ xsltSaveResultToFile(stdout, final_doc, stylesheet);
+ xsltFreeStylesheet(stylesheet);
xmlFree (final_doc);
+ xsltCleanupGlobals();
+ xmlCleanupParser();
- d(g_print ("docbook -> html took: %f s\n", g_timer_elapsed (timer, 0)));
- return TRUE;
+ return 0;
}
diff --git a/src/yelp-history.c b/src/yelp-history.c
index bf1e592e..c9fa76b1 100644
--- a/src/yelp-history.c
+++ b/src/yelp-history.c
@@ -322,4 +322,3 @@ yelp_history_new ()
{
return g_object_new (YELP_TYPE_HISTORY, NULL);
}
-
diff --git a/src/yelp-reader.c b/src/yelp-reader.c
index b4b145a0..4643b492 100644
--- a/src/yelp-reader.c
+++ b/src/yelp-reader.c
@@ -29,11 +29,13 @@
#include <libxslt/xsltutils.h>
#include <string.h>
+#include "yelp-cache.h"
#include "yelp-db2html.h"
#include "yelp-marshal.h"
#include "yelp-reader.h"
-#define d(x)
+#define d(x)
+
#define BUFFER_SIZE 16384
#define STAMP_MUTEX_LOCK g_mutex_lock(priv->stamp_mutex);
@@ -69,15 +71,17 @@ typedef struct {
ReaderQueueType type;
} ReaderQueueData;
-
static void reader_class_init (YelpReaderClass *klass);
static void reader_init (YelpReader *reader);
+#if 0
static void reader_db_start (ReaderThreadData *th_data);
static gint reader_db_write (ReaderThreadData *th_data,
const gchar *buffer,
gint len);
static gint reader_db_close (ReaderThreadData *th_data);
+#endif
+
static void reader_man_info_start (ReaderThreadData *th_data);
static void reader_file_start (ReaderThreadData *th_data);
@@ -86,7 +90,7 @@ static gboolean reader_check_cancelled (YelpReader *reader,
gint stamp);
static gpointer reader_start (ReaderThreadData *th_data);
static void reader_change_stamp (YelpReader *reader);
-static gboolean reader_idle_check_queue (ReaderThreadData *th_data);
+static gboolean reader_idle_check_queue (ReaderThreadData *th_data);
static ReaderQueueData *
reader_q_data_new (YelpReader *reader,
@@ -98,7 +102,8 @@ static void reader_q_data_free (ReaderQueueData *q_data);
/* FIXME: Solve this so we don't leak */
static void reader_th_data_free (ReaderThreadData *th_data);
#endif
-
+static gchar * reader_get_chunk (const gchar *document,
+ const gchar *section);
enum {
START,
@@ -209,6 +214,7 @@ reader_init (YelpReader *reader)
priv->thread_queue = g_async_queue_new ();
}
+#if 0
static void
reader_db_start (ReaderThreadData *th_data)
{
@@ -278,7 +284,11 @@ reader_db_write (ReaderThreadData *th_data, const gchar *buffer, gint len)
if (len <= 0) {
return 0;
}
-
+
+ g_print ("------------------------------------------\n");
+
+ g_print ("%s\n", buffer);
+
q_data = reader_q_data_new (reader, th_data->stamp,
READER_QUEUE_TYPE_DATA);
@@ -319,6 +329,7 @@ reader_db_close (ReaderThreadData *th_data)
return 0;
}
+#endif
static void
reader_man_info_start (ReaderThreadData *th_data)
@@ -330,7 +341,7 @@ reader_man_info_start (ReaderThreadData *th_data)
GError *error = NULL;
gint exit_status;
ReaderQueueData *q_data;
- gint stamp;
+ gint stamp;
g_return_if_fail (th_data != NULL);
@@ -363,13 +374,18 @@ reader_man_info_start (ReaderThreadData *th_data)
g_strdup_printf ("gnome2-info2html %s?%s",
yelp_uri_get_path (uri),
yelp_uri_get_section (uri));
- } else {
+ } else {
command_line =
g_strdup_printf ("gnome2-info2html %s",
yelp_uri_get_path (uri));
}
break;
+ case YELP_URI_TYPE_DOCBOOK_XML:
+ case YELP_URI_TYPE_DOCBOOK_SGML:
+ command_line = g_strdup_printf ("yelp-db2html %s",
+ yelp_uri_get_path (uri));
+ break;
default:
/* Set error */
break;
@@ -388,6 +404,10 @@ reader_man_info_start (ReaderThreadData *th_data)
NULL,
&exit_status,
&error /* FIXME */);
+ if (yelp_uri_get_type (uri) == YELP_URI_TYPE_DOCBOOK_XML ||
+ yelp_uri_get_type (uri) == YELP_URI_TYPE_DOCBOOK_SGML) {
+ yelp_cache_add (yelp_uri_get_path (uri), q_data->data);
+ }
g_free (command_line);
@@ -409,8 +429,28 @@ reader_man_info_start (ReaderThreadData *th_data)
g_signal_emit (reader, signals[ERROR], 0, error);
g_error_free (error);
} else {
- g_async_queue_push (priv->thread_queue, q_data);
+ if (yelp_uri_get_type (uri) == YELP_URI_TYPE_DOCBOOK_XML ||
+ yelp_uri_get_type (uri) == YELP_URI_TYPE_DOCBOOK_SGML) {
+ gchar *chunk;
+
+ if (yelp_uri_get_section (uri)) {
+ chunk = reader_get_chunk (q_data->data,
+ yelp_uri_get_section (uri));
+ } else {
+ chunk = reader_get_chunk (q_data->data,
+ "toc");
+ }
+
+ g_free (q_data->data);
+ q_data->data = chunk;
+
+ if (!q_data->data) {
+ q_data->data = g_strdup ("<html><body></body></html>");
+ }
+ }
+ g_async_queue_push (priv->thread_queue, q_data);
+
q_data = reader_q_data_new (reader, priv->stamp,
READER_QUEUE_TYPE_FINISHED);
@@ -532,7 +572,7 @@ reader_start (ReaderThreadData *th_data)
STAMP_MUTEX_UNLOCK;
/* FIXME: refs??? */
-/* reader_th_data_free (th_data); */
+/* reader_th_data_free(th_data); */
return NULL;
}
@@ -544,10 +584,10 @@ reader_start (ReaderThreadData *th_data)
STAMP_MUTEX_UNLOCK;
switch (yelp_uri_get_type (uri)) {
+/* reader_db_start (th_data); */
+/* break; */
case YELP_URI_TYPE_DOCBOOK_XML:
case YELP_URI_TYPE_DOCBOOK_SGML:
- reader_db_start (th_data);
- break;
case YELP_URI_TYPE_MAN:
case YELP_URI_TYPE_INFO:
reader_man_info_start (th_data);
@@ -720,6 +760,75 @@ reader_th_data_free (ReaderThreadData *th_data)
}
#endif
+static gchar *
+reader_get_chunk (const gchar *document, const gchar *section)
+{
+ gchar *header;
+ gchar *chunk;
+ const gchar *footer;
+ gchar *ret_val;
+ const gchar *start;
+ const gchar *end;
+ gchar *tag;
+ GTimer *timer;
+
+/* g_print ("%s\n", document); */
+
+ timer = g_timer_new ();
+
+ end = strstr (document, "<!-- End of header -->");
+
+ if (!end) {
+ g_warning ("Wrong type of document\n");
+ return NULL;
+ }
+
+ header = g_strndup (document, end - document);
+
+ tag = g_strdup_printf ("<!-- Start of chunk: [%s] -->", section);
+ start = strstr (document, tag);
+ g_free (tag);
+
+ if (!start) {
+ g_warning ("Document doesn't include section: %s", section);
+ g_free (header);
+
+ return NULL;
+ }
+
+ end = strstr (start, "<!-- End of chunk -->");
+
+ if (!end) {
+ g_warning ("Document is doesn't contain end tag for section: %s",
+ section);
+ g_free (header);
+
+ return NULL;
+ }
+
+ chunk = g_strndup (start, end - start);
+
+ footer = strstr (document, "<!-- Start of footer -->");
+
+ if (!footer) {
+ g_warning ("Couldn't find footer in document");
+ g_free (header);
+ g_free (chunk);
+
+ return NULL;
+ }
+
+ ret_val = g_strconcat (header, chunk, footer, NULL);
+
+ g_free (header);
+ g_free (chunk);
+
+/* g_print ("Finding chunk took: %f seconds\n", */
+/* g_timer_elapsed (timer, 0)); */
+
+ return ret_val;
+}
+
YelpReader *
yelp_reader_new ()
{
@@ -755,14 +864,56 @@ yelp_reader_start (YelpReader *reader, YelpURI *uri)
stamp = priv->stamp;
+ STAMP_MUTEX_UNLOCK;
+
th_data = g_new0 (ReaderThreadData, 1);
th_data->reader = g_object_ref (reader);
th_data->uri = yelp_uri_ref (uri);
th_data->stamp = stamp;
- STAMP_MUTEX_UNLOCK;
+ if (yelp_uri_get_type (uri) == YELP_URI_TYPE_DOCBOOK_XML ||
+ yelp_uri_get_type (uri) == YELP_URI_TYPE_DOCBOOK_SGML) {
+ const gchar *document;
+ gchar *chunk;
- g_idle_add ((GSourceFunc) reader_idle_check_queue, th_data);
+ document = yelp_cache_lookup (yelp_uri_get_path (uri));
+
+ if (document) {
+ if (yelp_uri_get_section (uri)) {
+ chunk = reader_get_chunk (document,
+ yelp_uri_get_section (uri));
+ } else {
+ chunk = reader_get_chunk (document, "toc");
+ }
+
+ if (chunk) {
+ ReaderQueueData *q_data;
+
+ q_data = reader_q_data_new (reader, stamp,
+ READER_QUEUE_TYPE_START);
+ g_async_queue_push (priv->thread_queue,
+ q_data);
+
+ q_data = reader_q_data_new (reader, stamp,
+ READER_QUEUE_TYPE_DATA);
+
+ q_data->data = chunk;
+ g_async_queue_push (priv->thread_queue,
+ q_data);
+
+ q_data = reader_q_data_new (reader, stamp,
+ READER_QUEUE_TYPE_FINISHED);
+
+ g_async_queue_push (priv->thread_queue,
+ q_data);
+
+ g_idle_add ((GSourceFunc) reader_idle_check_queue, th_data);
+ return;
+ }
+ }
+ }
+
+ g_timeout_add (100, (GSourceFunc) reader_idle_check_queue, th_data);
g_thread_create ((GThreadFunc) reader_start, th_data,
TRUE,