Beispiel #1
0
/**
 * djvu_text_page_selection_process_box:
 * @page: #DjvuTextPage instance
 * @p: s-expression to append bounding box of
 * @delimit: character/word/... delimiter
 *
 * Appends bounding box of the line containing miniexp_t to page->results
 *
 * Returns: whether the end was not reached in this s-expression
 */
static gboolean
djvu_text_page_selection_process_box (DjvuTextPage *page,
				      miniexp_t     p,
				      int           delimit)
{
	if (page->results || p == page->start) {
		EvRectangle box;
		const char *text;

		box.x1 = miniexp_to_int (miniexp_nth (1, p));
		box.y1 = miniexp_to_int (miniexp_nth (2, p));
		box.x2 = miniexp_to_int (miniexp_nth (3, p));
		box.y2 = miniexp_to_int (miniexp_nth (4, p));
		text = miniexp_to_str (miniexp_nth (5, p));

		if (text != NULL && text[0] != '\0') {
			if (!(delimit & 2) && page->results != NULL) {
				EvRectangle *union_box = (EvRectangle *)page->results->data;

                                /* If still on the same line, add box to union */
				djvu_text_page_union (union_box, &box);
			} else {
				/* A new line, a new box */
				page->results = g_list_prepend (page->results, ev_rectangle_copy (&box));
			}
		}

		if (p == page->end)
			return FALSE;
	}
	return TRUE;
}
void Model::DjVuDocument::loadProperties(QStandardItemModel* propertiesModel) const
{
    Document::loadProperties(propertiesModel);

    QMutexLocker mutexLocker(&m_mutex);

    propertiesModel->setColumnCount(2);

    miniexp_t annoExp;

    while(true)
    {
        annoExp = ddjvu_document_get_anno(m_document, TRUE);

        if(annoExp == miniexp_dummy)
        {
            clearMessageQueue(m_context, true);
        }
        else
        {
            break;
        }
    }

    const int annoLength = miniexp_length(annoExp);

    for(int annoN = 0; annoN < annoLength; ++annoN)
    {
        miniexp_t listExp = miniexp_nth(annoN, annoExp);
        const int listLength = miniexp_length(listExp);

        if(listLength <= 1 || qstrncmp(miniexp_to_name(miniexp_nth(0, listExp)), "metadata", 8) != 0)
        {
            continue;
        }

        for(int listN = 1; listN < listLength; ++listN)
        {
            miniexp_t keyValueExp = miniexp_nth(listN, listExp);

            if(miniexp_length(keyValueExp) != 2)
            {
                continue;
            }

            const QString key = QString::fromUtf8(miniexp_to_name(miniexp_nth(0, keyValueExp)));
            const QString value = QString::fromUtf8(miniexp_to_str(miniexp_nth(1, keyValueExp)));

            if(!key.isEmpty() && !value.isEmpty())
            {
                propertiesModel->appendRow(QList< QStandardItem* >() << new QStandardItem(key) << new QStandardItem(value));
            }
        }
    }

    ddjvu_miniexp_release(m_document, annoExp);
}
static void loadOutline(miniexp_t outlineExp, int offset, QStandardItem* parent, const QHash< QString, int >& indexByName)
{
    const int outlineLength = miniexp_length(outlineExp);

    for(int outlineN = qMax(0, offset); outlineN < outlineLength; ++outlineN)
    {
        miniexp_t bookmarkExp = miniexp_nth(outlineN, outlineExp);
        const int bookmarkLength = miniexp_length(bookmarkExp);

        if(bookmarkLength <= 1 || !miniexp_stringp(miniexp_nth(0, bookmarkExp)) || !miniexp_stringp(miniexp_nth(1, bookmarkExp)))
        {
            continue;
        }

        const QString title = QString::fromUtf8(miniexp_to_str(miniexp_nth(0, bookmarkExp)));
        QString destination = QString::fromUtf8(miniexp_to_str(miniexp_nth(1, bookmarkExp)));

        if(!title.isEmpty() && !destination.isEmpty())
        {
            if(destination.at(0) == QLatin1Char('#'))
            {
                destination.remove(0,1);

                bool ok = false;
                int destinationPage = destination.toInt(&ok);

                if(!ok)
                {
                    if(indexByName.contains(destination))
                    {
                        destinationPage = indexByName[destination] + 1;
                    }
                    else
                    {
                        continue;
                    }
                }

                QStandardItem* item = new QStandardItem(title);
                item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);

                item->setData(destinationPage, Qt::UserRole + 1);

                QStandardItem* pageItem = item->clone();
                pageItem->setText(QString::number(destinationPage));
                pageItem->setTextAlignment(Qt::AlignRight);

                parent->appendRow(QList< QStandardItem* >() << item << pageItem);

                if(bookmarkLength >= 3)
                {
                    loadOutline(bookmarkExp, 2, item, indexByName);
                }
            }
        }
    }
}
Beispiel #4
0
static int walkTableOfContent(lua_State *L, miniexp_t r, int *count, int depth) {
	depth++;

	miniexp_t lista = miniexp_cdr(r); // go inside bookmars in the list

	int length = miniexp_length(r);
	int counter = 0;
	const char* page_name;
	int page_number;

	while(counter < length-1) {
		lua_pushnumber(L, *count);
		lua_newtable(L);

		lua_pushstring(L, "page");
		page_name = miniexp_to_str(miniexp_car(miniexp_cdr(miniexp_nth(counter, lista))));
		if(page_name != NULL && page_name[0] == '#') {
			errno = 0;
			page_number = strtol(page_name + 1, NULL, 10);
			if(!errno) {
				lua_pushnumber(L, page_number);
			} else {
				/* we can not parse this as a number, TODO: parse page names */
				lua_pushnumber(L, -1);
			}
		} else {
			/* something we did not expect here */
			lua_pushnumber(L, -1);
		}
		lua_settable(L, -3);

		lua_pushstring(L, "depth");
		lua_pushnumber(L, depth);
		lua_settable(L, -3);

		lua_pushstring(L, "title");
		lua_pushstring(L, miniexp_to_str(miniexp_car(miniexp_nth(counter, lista))));
		lua_settable(L, -3);

		lua_settable(L, -3);

		(*count)++;

		if (miniexp_length(miniexp_cdr(miniexp_nth(counter, lista))) > 1) {
			walkTableOfContent(L, miniexp_cdr(miniexp_nth(counter, lista)), count, depth);
		}
		counter++;
	}
	return 0;
}
Beispiel #5
0
static void
djvu_text_page_limits_process (DjvuTextPage *page,
			       miniexp_t     p, 
			       EvRectangle  *rect)
{
	EvRectangle current;
	
	current.x1 = miniexp_to_int (miniexp_nth (1, p));
	current.y1 = miniexp_to_int (miniexp_nth (2, p));
	current.x2 = miniexp_to_int (miniexp_nth (3, p));
	current.y2 = miniexp_to_int (miniexp_nth (4, p));
	if (current.x2 >= rect->x1 && current.y1 <= rect->y2 &&
	    current.x1 <= rect->x2 && current.y2 >= rect->y1) {
	    	if (page->start == miniexp_nil)
	    		page->start = p;
	    	page->end = p;
	}
}
Beispiel #6
0
static void
djvu_text_page_limits_process (DjvuTextPage *page,
			       miniexp_t     p, 
			       EvRectangle  *rect)
{
	EvRectangle current;
	const char *text;
	
	current.x1 = miniexp_to_int (miniexp_nth (1, p));
	current.y1 = miniexp_to_int (miniexp_nth (2, p));
	current.x2 = miniexp_to_int (miniexp_nth (3, p));
	current.y2 = miniexp_to_int (miniexp_nth (4, p));
	text = miniexp_to_str (miniexp_nth (5, p));
	if (current.x2 >= rect->x1 && current.y1 <= rect->y2 &&
	    current.x1 <= rect->x2 && current.y2 >= rect->y1 &&
	    text != NULL && text[0] != '\0') {
	    	if (page->start == miniexp_nil)
	    		page->start = p;
	    	page->end = p;
	}
}
Beispiel #7
0
/**
 * djvu_text_page_sexpr_process:
 * @page: #DjvuTextPage instance
 * @p: s-expression to append
 * @start: first s-expression in the selection
 * @end: last s-expression in the selection
 * 
 * Appends the rectangle defined by @p to the internal bounding box rectangle.
 * 
 * Returns: whether the end was not reached in this s-expression
 */
static gboolean
djvu_text_page_sexpr_process (DjvuTextPage *page, 
                              miniexp_t     p,
                              miniexp_t     start, 
                              miniexp_t     end)
{
	if (page->bounding_box || p == start) {
		EvRectangle *new_rectangle = g_new (EvRectangle, 1);
		new_rectangle->x1 = miniexp_to_int (miniexp_nth (1, p));
		new_rectangle->y1 = miniexp_to_int (miniexp_nth (2, p));
		new_rectangle->x2 = miniexp_to_int (miniexp_nth (3, p));
		new_rectangle->y2 = miniexp_to_int (miniexp_nth (4, p));
		if (page->bounding_box) {
			djvu_text_page_union (page->bounding_box,
					      new_rectangle);
			g_free (new_rectangle);
		} else
			page->bounding_box = new_rectangle;
		if (p == end)
			return FALSE;
	}
	return TRUE;
}
static QString loadText(miniexp_t textExp, const QRect& rect, int pageHeight)
{
    const int textLength = miniexp_length(textExp);

    if(textLength >= 6 && miniexp_symbolp(miniexp_nth(0, textExp)))
    {
        const int xmin = miniexp_to_int(miniexp_nth(1, textExp));
        const int ymin = miniexp_to_int(miniexp_nth(2, textExp));
        const int xmax = miniexp_to_int(miniexp_nth(3, textExp));
        const int ymax = miniexp_to_int(miniexp_nth(4, textExp));

        if(rect.intersects(QRect(xmin, pageHeight - ymax, xmax - xmin, ymax - ymin)))
        {
            if(qstrncmp(miniexp_to_name(miniexp_nth(0, textExp)), "word", 4) == 0)
            {
                return QString::fromUtf8(miniexp_to_str(miniexp_nth(5, textExp)));
            }
            else
            {
                QStringList text;

                for(int textN = 5; textN < textLength; ++textN)
                {
                    text.append(loadText(miniexp_nth(textN, textExp), rect, pageHeight));
                }

                if(qstrncmp(miniexp_to_name(miniexp_nth(0, textExp)), "line", 4) == 0)
                {
                    return text.join(" ");
                }
                else
                {
                    return text.join("\n");
                }
            }
        }
    }

    return QString();
}
void guFolderInspector::extractIsbnsFromDjvu(QString fileName, QList<QString> &ISBNList)
{
    ctx = ddjvu_context_create("lgUploader"); //ddjvu_document_create_by_filename
    doc = ddjvu_document_create_by_filename_utf8(ctx, fileName.toUtf8(), 1);
    while (! ddjvu_document_decoding_done(doc));
    int  numOfPages = ddjvu_document_get_pagenum(doc); //количество страниц - строго!
    //QByteArray b = QFile::encodeName(fileName);
    //doc = ddjvu_document_create_by_filename(ctx, b, 1);
    if(!doc)
        qDebug() << "error create doc";
    if(!ctx)
        qDebug() << "error create context";


    const char *lvl = "page";
    //начало перебора по страницам
    isbnMethods find;
    int numOfSearchPages = 15;
    //qDebug() << "num of pages " << numOfPages;
    if(numOfPages < numOfSearchPages)
    {
        numOfSearchPages = numOfPages;
    }
    for (int pageCount = 0 ; pageCount < numOfSearchPages ; pageCount++)
    {

        miniexp_t r = miniexp_nil;
        while ((r = ddjvu_document_get_pagetext(doc, pageCount ,lvl))==miniexp_dummy);
        r = miniexp_nth(5, r);
        //if ( r == miniexp_nil )
        //    qDebug() << "r = null";
        const char *pageDumpArr = miniexp_to_str( r );
        QString pageDump( QString::fromUtf8( pageDumpArr ));

        find.findIsbns(pageDump, ISBNList);

        //qDebug() << fileName << " content: \n" <<  pageDump ;
    }
    //конец перебора по страницам
    if (doc)
        ddjvu_document_release(doc); //освобождаем контекст документа
    if (ctx)
        ddjvu_context_release(ctx); //освобождаем контескт приложени¤ (возможно стоит оставить)

}
Beispiel #10
0
/**
 * djvu_text_page_selection_process:
 * @page: #DjvuTextPage instance
 * @p: s-expression to append
 * @delimit: character/word/... delimiter
 * 
 * Appends the string in @p to the page text.
 * 
 * Returns: whether the end was not reached in this s-expression
 */
static gboolean
djvu_text_page_selection_process (DjvuTextPage *page, 
                                  miniexp_t     p,
                                  int           delimit)
{
	if (page->text || p == page->start) {
		char *token_text = (char *) miniexp_to_str (miniexp_nth (5, p));
		if (page->text) {
			char *new_text =
			    g_strjoin (delimit & 2 ? "\n" : 
			    	       delimit & 1 ? " " : NULL,
				       page->text, token_text,
				       NULL);
			g_free (page->text);
			page->text = new_text;
		} else
			page->text = g_strdup (token_text);
		if (p == page->end) 
			return FALSE;
	}
	return TRUE;
}
Beispiel #11
0
void
dopage(int pageno)
{
  miniexp_t r = miniexp_nil;
  const char *lvl = (detail) ? detail : "page";
  while ((r = ddjvu_document_get_pagetext(doc,pageno-1,lvl))==miniexp_dummy)
    handle(TRUE);
  if (detail)
    {
      miniexp_io_t io;
      miniexp_io_init(&io);
      io.p_print7bits = &escape;
      miniexp_pprint_r(&io, r, 72);
    }
  else if ((r = miniexp_nth(5, r)) && miniexp_stringp(r))
    {
      const char *s = miniexp_to_str(r); 
      if (! escape)
        fputs(s, stdout);
      else
        {
          unsigned char c;
          while ((c = *(unsigned char*)s++))
            {
              bool esc = false;
              if (c == '\\' || c >= 0x7f)
                esc = true; /* non-ascii */
              if (c < 0x20 && !strchr("\013\035\037\012", c))
                esc = true; /* non-printable other than separators */
              if (esc)
                printf("\\%03o", c);
              else
                putc(c, stdout);
            }
        }
      fputs("\n\f", stdout);
    }
}
void Model::DjVuDocument::loadOutline(QStandardItemModel* outlineModel) const
{
    Document::loadOutline(outlineModel);

    QMutexLocker mutexLocker(&m_mutex);

    miniexp_t outlineExp;

    while(true)
    {
        outlineExp = ddjvu_document_get_outline(m_document);

        if(outlineExp == miniexp_dummy)
        {
            clearMessageQueue(m_context, true);
        }
        else
        {
            break;
        }
    }

    if(miniexp_length(outlineExp) <= 1)
    {
        return;
    }

    if(qstrncmp(miniexp_to_name(miniexp_nth(0, outlineExp)), "bookmarks", 9) != 0)
    {
        return;
    }

    ::loadOutline(outlineExp, 1, outlineModel->invisibleRootItem(), m_indexByName);

    ddjvu_miniexp_release(m_document, outlineExp);
}
QList< QRectF > Model::DjVuPage::search(const QString& text, bool matchCase) const
{
    QMutexLocker mutexLocker(&m_parent->m_mutex);

    miniexp_t pageTextExp;

    while(true)
    {
        pageTextExp = ddjvu_document_get_pagetext(m_parent->m_document, m_index, "word");

        if(pageTextExp == miniexp_dummy)
        {
            clearMessageQueue(m_parent->m_context, true);
        }
        else
        {
            break;
        }
    }

    QList< miniexp_t > words;
    QList< QRectF > results;

    words.append(pageTextExp);

    QRectF rect;
    int index = 0;

    while(!words.isEmpty())
    {
        miniexp_t textExp = words.takeFirst();

        const int textLength = miniexp_length(textExp);

        if(textLength >= 6 && miniexp_symbolp(miniexp_nth(0, textExp)))
        {
            if(qstrncmp(miniexp_to_name(miniexp_nth(0, textExp)), "word", 4) == 0)
            {
                const QString word = QString::fromUtf8(miniexp_to_str(miniexp_nth(5, textExp)));

                if(text.indexOf(word, index, matchCase ? Qt::CaseSensitive : Qt::CaseInsensitive) == index)
                {
                    const int xmin = miniexp_to_int(miniexp_nth(1, textExp));
                    const int ymin = miniexp_to_int(miniexp_nth(2, textExp));
                    const int xmax = miniexp_to_int(miniexp_nth(3, textExp));
                    const int ymax = miniexp_to_int(miniexp_nth(4, textExp));

                    rect = rect.united(QRectF(xmin, m_size.height() - ymax, xmax - xmin, ymax - ymin));

                    index += word.length();

                    while(text.length() > index && text.at(index).isSpace())
                    {
                        ++index;
                    }

                    if(text.length() == index)
                    {
                        results.append(rect);

                        rect = QRectF();
                        index = 0;
                    }
                }
                else
                {
                    rect = QRectF();
                    index = 0;
                }
            }
            else
            {
                for(int textN = 5; textN < textLength; ++textN)
                {
                    words.append(miniexp_nth(textN, textExp));
                }
            }
        }
    }

    ddjvu_miniexp_release(m_parent->m_document, pageTextExp);

    QTransform transform = QTransform::fromScale(72.0 / m_resolution, 72.0 / m_resolution);

    for(int index = 0; index < results.size(); ++index)
    {
        results[index] = transform.mapRect(results[index]);
    }

    return results;
}
QList< Model::Link* > Model::DjVuPage::links() const
{
    QMutexLocker mutexLocker(&m_parent->m_mutex);

    QList< Link* > links;

    miniexp_t pageAnnoExp;

    while(true)
    {
        pageAnnoExp = ddjvu_document_get_pageanno(m_parent->m_document, m_index);

        if(pageAnnoExp == miniexp_dummy)
        {
            clearMessageQueue(m_parent->m_context, true);
        }
        else
        {
            break;
        }
    }

    const int pageAnnoLength = miniexp_length(pageAnnoExp);

    for(int pageAnnoN = 0; pageAnnoN < pageAnnoLength; ++pageAnnoN)
    {
        miniexp_t linkExp = miniexp_nth(pageAnnoN, pageAnnoExp);

        if(miniexp_length(linkExp) <= 3 || qstrncmp(miniexp_to_name(miniexp_nth(0, linkExp)), "maparea", 7 ) != 0 || !miniexp_symbolp(miniexp_nth(0, miniexp_nth(3, linkExp))))
        {
            continue;
        }

        const QString type = QString::fromUtf8(miniexp_to_name(miniexp_nth(0, miniexp_nth(3, linkExp))));

        if(type == QLatin1String("rect") || type == QLatin1String("oval") || type == QLatin1String("poly"))
        {
            // boundary

            QPainterPath boundary;

            miniexp_t areaExp = miniexp_nth(3, linkExp);
            const int areaLength = miniexp_length( areaExp );

            if(areaLength == 5 && (type == QLatin1String("rect") || type == QLatin1String("oval")))
            {
                QPoint p(miniexp_to_int(miniexp_nth(1, areaExp)), miniexp_to_int(miniexp_nth(2, areaExp)));
                QSize s(miniexp_to_int(miniexp_nth(3, areaExp)), miniexp_to_int(miniexp_nth(4, areaExp)));

                p.setY(m_size.height() - s.height() - p.y());

                const QRectF r(p, s);

                if(type == QLatin1String("rect"))
                {
                    boundary.addRect(r);
                }
                else
                {
                    boundary.addEllipse(r);
                }
            }
            else if(areaLength > 0 && areaLength % 2 == 1 && type == QLatin1String("poly"))
            {
                QPolygon polygon;

                for(int areaExpN = 1; areaExpN < areaLength; areaExpN += 2)
                {
                    QPoint p(miniexp_to_int(miniexp_nth(areaExpN, areaExp)), miniexp_to_int(miniexp_nth(areaExpN + 1, areaExp)));

                    p.setY(m_size.height() - p.y());

                    polygon << p;
                }

                boundary.addPolygon(polygon);
            }

            if(boundary.isEmpty())
            {
                continue;
            }

            boundary = QTransform::fromScale(1.0 / m_size.width(), 1.0 / m_size.height()).map(boundary);

            // target

            QString target;

            miniexp_t targetExp = miniexp_nth(1, linkExp);

            if(miniexp_stringp(targetExp))
            {
                target = QString::fromUtf8(miniexp_to_str(miniexp_nth(1, linkExp)));
            }
            else if(miniexp_length(targetExp) == 3 && qstrncmp(miniexp_to_name(miniexp_nth(0, targetExp)), "url", 3) == 0)
            {
                target = QString::fromUtf8(miniexp_to_str(miniexp_nth(1, targetExp)));
            }

            if(target.isEmpty())
            {
                continue;
            }

            if(target.at(0) == QLatin1Char('#'))
            {
                target.remove(0, 1);

                bool ok = false;
                int targetPage = target.toInt(&ok);

                if(!ok)
                {
                    if(m_parent->m_indexByName.contains(target))
                    {
                        targetPage = m_parent->m_indexByName[target] + 1;
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    targetPage = (target.at(0) == QLatin1Char('+') || target.at(0) == QLatin1Char('-')) ? m_index + targetPage : targetPage;
                }

                links.append(new Link(boundary, targetPage));
            }
            else
            {
                links.append(new Link(boundary, target));
            }
        }
    }

    ddjvu_miniexp_release(m_parent->m_document, pageAnnoExp);

    return links;
}
Beispiel #15
0
/*
 * Return a table like following:
 * {
 *    -- a line entry
 *    1 = {
 *       1 = {word="This", x0=377, y0=4857, x1=2427, y1=5089},
 *       2 = {word="is", x0=377, y0=4857, x1=2427, y1=5089},
 *       3 = {word="Word", x0=377, y0=4857, x1=2427, y1=5089},
 *       4 = {word="List", x0=377, y0=4857, x1=2427, y1=5089},
 *       x0 = 377, y0 = 4857, x1 = 2427, y1 = 5089,
 *    },
 *
 *    -- an other line entry
 *    2 = {
 *       1 = {word="This", x0=377, y0=4857, x1=2427, y1=5089},
 *       2 = {word="is", x0=377, y0=4857, x1=2427, y1=5089},
 *       x0 = 377, y0 = 4857, x1 = 2427, y1 = 5089,
 *    },
 * }
 */
static int getPageText(lua_State *L) {
	DjvuDocument *doc = (DjvuDocument*) luaL_checkudata(L, 1, "djvudocument");
	int pageno = luaL_checkint(L, 2);

	/* get page height for coordinates transform */
	ddjvu_pageinfo_t info;
	ddjvu_status_t r;
	while ((r=ddjvu_document_get_pageinfo(
				   doc->doc_ref, pageno-1, &info))<DDJVU_JOB_OK) {
		handle(L, doc->context, TRUE);
	}
	if (r>=DDJVU_JOB_FAILED)
		return luaL_error(L, "cannot get page #%d information", pageno);

	/* start retrieving page text */
	miniexp_t sexp, se_line, se_word;
	int i = 1, j = 1, counter_l = 1, counter_w=1,
		nr_line = 0, nr_word = 0;
	const char *word = NULL;

	while ((sexp = ddjvu_document_get_pagetext(doc->doc_ref, pageno-1, "word"))
				== miniexp_dummy) {
		handle(L, doc->context, True);
	}

	/* throuw page info and obtain lines info, after this, sexp's entries
	 * are lines. */
	sexp = miniexp_cdr(sexp);
	/* get number of lines in a page */
	nr_line = miniexp_length(sexp);
	/* table that contains all the lines */
	lua_newtable(L);

	counter_l = 1;
	for(i = 1; i <= nr_line; i++) {
		/* retrive one line entry */
		se_line = miniexp_nth(i, sexp);
		nr_word = miniexp_length(se_line);
		if (nr_word == 0) {
			continue;
		}

		/* subtable that contains words in a line */
		lua_pushnumber(L, counter_l);
		lua_newtable(L);
		counter_l++;

		/* set line position */
		lua_pushstring(L, "x0");
		lua_pushnumber(L, miniexp_to_int(miniexp_nth(1, se_line)));
		lua_settable(L, -3);

		lua_pushstring(L, "y1");
		lua_pushnumber(L,
				info.height - miniexp_to_int(miniexp_nth(2, se_line)));
		lua_settable(L, -3);

		lua_pushstring(L, "x1");
		lua_pushnumber(L, miniexp_to_int(miniexp_nth(3, se_line)));
		lua_settable(L, -3);

		lua_pushstring(L, "y0");
		lua_pushnumber(L,
				info.height - miniexp_to_int(miniexp_nth(4, se_line)));
		lua_settable(L, -3);

		/* now loop through each word in the line */
		counter_w = 1;
		for(j = 1; j <= nr_word; j++) {
			/* retrive one word entry */
			se_word = miniexp_nth(j, se_line);
			/* check to see whether the entry is empty */
			word = miniexp_to_str(miniexp_nth(5, se_word));
			if (!word) {
				continue;
			}

			/* create table that contains info for a word */
			lua_pushnumber(L, counter_w);
			lua_newtable(L);
			counter_w++;

			/* set word info */
			lua_pushstring(L, "x0");
			lua_pushnumber(L, miniexp_to_int(miniexp_nth(1, se_word)));
			lua_settable(L, -3);

			lua_pushstring(L, "y1");
			lua_pushnumber(L,
					info.height - miniexp_to_int(miniexp_nth(2, se_word)));
			lua_settable(L, -3);

			lua_pushstring(L, "x1");
			lua_pushnumber(L, miniexp_to_int(miniexp_nth(3, se_word)));
			lua_settable(L, -3);

			lua_pushstring(L, "y0");
			lua_pushnumber(L,
					info.height - miniexp_to_int(miniexp_nth(4, se_word)));
			lua_settable(L, -3);

			lua_pushstring(L, "word");
			lua_pushstring(L, word);
			lua_settable(L, -3);

			/* set word entry to line subtable */
			lua_settable(L, -3);
		} /* end of for (j) */

		/* set line entry to page text table */
		lua_settable(L, -3);
	} /* end of for (i) */

	return 1;
}