⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dw_ext_iterator.c

📁 浏览器的源代码,可移植到嵌入式设备.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * File: dw_ext_iterator.c * * Copyright (C) 2002 Sebastian Geerken <S.Geerken@ping.de> * * 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. *//* * DwExtIterator is an extension of DwIterator, which stores * DwIterator's in a stack, for cases where recursions are not * possible. * * DwWordIterator is a simple wrapper for DwExtIterator, which splits * text segments into words, and is used for text search (in * findtext.c) * * todo: In some cases (e.g. for "<i>foo</i>bar"), DwIterator and *       DwExtIterator return two words, where there is actually only *       one.  In this case, iterator->content.space is set to FALSE. *       DwWordIterator currently ignores this flag, but instead *       returns two words, instead of concaternating them to one. */#include "dw_ext_iterator.h"#include "list.h"#include "misc.h"/*#define DEBUG_LEVEL 1*/#include "debug.h"/* * The following two functions are used by a_Dw_extiterator_new, when the * passed DwIterator points to a widget. Since a DwExtIterator never returns * a widget, the DwIterator has to be corrected, by searching for the next * content downwards (within the widget pointed to), forwards, and backwards * (in the traversed tree). *//* * Search downwards. If from_end is TRUE, start search at the end, * otherwise at the beginning. * The pararameter indent is only for debugging purposes. */static DwIterator *Dw_ext_iterator_search_downward (DwIterator *it,                                                    gboolean from_end,                                                    int indent){   DwIterator *it2, *it3;   DEBUG_MSG (1, "%*smoving down (%swards) from %s\n",              indent, "", from_end ? "back" : "for", a_Dw_iterator_text (it));   g_return_val_if_fail (it->content.type == DW_CONTENT_WIDGET, NULL);   it2 = a_Dw_widget_iterator (it->content.data.widget, it->mask, from_end);   if (it2 == NULL) {      /* Moving downwards failed. */      DEBUG_MSG (1, "%*smoving down failed\n", indent, "");      return NULL;   }   while (from_end ? a_Dw_iterator_prev (it2) : a_Dw_iterator_next (it2)) {      DEBUG_MSG (1, "%*sexamining %s\n",                 indent, "", a_Dw_iterator_text (it2));      if (it2->content.type == DW_CONTENT_WIDGET) {         /* Another widget. Search in it downwards. */         it3 = Dw_ext_iterator_search_downward (it2, from_end, indent + 3);         if (it3 != NULL) {            a_Dw_iterator_free (it2);            return it3;         }         /* Else continue in this widget. */      } else {         /* Success! */         DEBUG_MSG (1, "%*smoving down succeeded: %s\n",                    indent, "", a_Dw_iterator_text (it2));         return it2;      }   }   /* Nothing found. */   a_Dw_iterator_free (it2);   DEBUG_MSG (1, "%*smoving down failed (nothing found)\n", indent, "");   return NULL;}/* * Search sidewards. from_end specifies the direction, FALSE means forwards, * TRUE means backwards. * The pararameter indent is only for debugging purposes. */static DwIterator *Dw_ext_iterator_search_sideward (DwIterator *it,                                                    gboolean from_end,                                                    int indent){   DwIterator *it2, *it3;   DEBUG_MSG (1, "%*smoving %swards from %s\n",              indent, "", from_end ? "back" : "for", a_Dw_iterator_text (it));   g_return_val_if_fail (it->content.type == DW_CONTENT_WIDGET, NULL);   it2 = a_Dw_iterator_clone (it);   while (from_end ? a_Dw_iterator_prev (it2) : a_Dw_iterator_next (it2)) {      if (it2->content.type == DW_CONTENT_WIDGET) {         /* Search downwards in this widget. */         it3 = Dw_ext_iterator_search_downward (it2, from_end, indent + 3);         if (it3 != NULL) {            a_Dw_iterator_free (it2);            DEBUG_MSG (1, "%*smoving %swards succeeded: %s\n",                       indent, "", from_end ? "back" : "for",                       a_Dw_iterator_text (it3));            return it3;         }         /* Else continue in this widget. */      } else {         /* Success! */         DEBUG_MSG (1, "%*smoving %swards succeeded: %s\n",                    indent, "", from_end ? "back" : "for",                    a_Dw_iterator_text (it2));         return it2;      }   }   /* Nothing found, go upwards in the tree (if possible). */   a_Dw_iterator_free (it2);   if (it->widget->parent) {      it2 = a_Dw_widget_iterator (it->widget->parent, it->mask, FALSE);      while (TRUE) {         if (!a_Dw_iterator_next(it2)) {            g_warning ("BUG in DwExtIterator!");            a_Dw_iterator_free (it2);            return NULL;         }         if (it2->content.type == DW_CONTENT_WIDGET &&             it2->content.data.widget == it->widget) {            it3 = Dw_ext_iterator_search_sideward (it2, from_end, indent + 3);            a_Dw_iterator_free (it2);            DEBUG_MSG (1, "%*smoving %swards succeeded: %s\n",                       indent, "", from_end ? "back" : "for",                       a_Dw_iterator_text (it3));            return it3;         }      }   }   /* Nothing found at all. */   DEBUG_MSG (1, "%*smoving %swards failed (nothing found)\n",              indent, "", from_end ? "back" : "for");   return NULL;}/* * Create a new DwExtIterator from an existing DwIterator. The content of the * return value will be the content of "it". If within the widget tree, there * is no non-widget content, NULL is returned. * * NOTES: * (i)  If you want to continue using "it", pass a_Dw_iterator_clone (it). * (ii) The mask of "it" must include DW_CONTENT_WIDGET, but *      a_Dw_ext_iterator_next will never return widgets. * * TODO: Change in the near future: NULL is by all other functions within this * module interpreted as an "empty" iterator, which makes code outside more * robust. */DwExtIterator* a_Dw_ext_iterator_new (DwIterator *it){   DwExtIterator *eit;   DwIterator *it2;   DwWidget *w;   int sp;   DEBUG_MSG (1, "a_Dw_ext_iterator_new: %s\n", a_Dw_iterator_text (it));   /* If "it" points to a widget, find a near non-widget content,    * since an DwExtIterator should never return widgets. */   if (it->content.type == DW_CONTENT_WIDGET) {      /* The second argument of Dw_ext_iterator_search_downward is       * actually a matter of taste :-) */      if ((it2 = Dw_ext_iterator_search_downward (it, FALSE, 3)) ||          (it2 = Dw_ext_iterator_search_sideward (it, FALSE, 3)) ||          (it2 = Dw_ext_iterator_search_sideward (it, TRUE, 3))) {         a_Dw_iterator_free (it);         it = it2;      } else {         /* This may happen, when a page does not contain any          * non-widget content. */         DEBUG_MSG (1, "a_Dw_ext_iterator_new got totally helpless!\n");         a_Dw_iterator_free (it);         return NULL;      }   }   DEBUG_MSG (1, "  => %s\n", a_Dw_iterator_text (it));   eit = g_new (DwExtIterator, 1);   eit->stack_top = 0;   /* If this widget has parents, we must construct appropiate iterators.    * todo: There may be a faster way instead of iterating through the    * parent widgets. */   for (w = it->widget; w->parent != NULL; w = w->parent)      eit->stack_top++;   eit->stack_max = 4;   while (eit->stack_top >= eit->stack_max)      eit->stack_max <<= 1;   eit->stack = g_new (DwIterator*, eit->stack_max);   /* Construct the iterators. */   for (w = it->widget, sp = eit->stack_top - 1;       w->parent != NULL;       w = w->parent, sp--) {      eit->stack[sp] = a_Dw_widget_iterator (w->parent, it->mask, FALSE);      while (TRUE) {         if (!a_Dw_iterator_next(eit->stack[sp])) {            g_warning ("BUG in DwExtIterator!");            return NULL;         }         if (eit->stack[sp]->content.type == DW_CONTENT_WIDGET &&             eit->stack[sp]->content.data.widget == w)            break;      }   }   eit->stack[eit->stack_top] = it;   eit->content = it->content;   return eit;}/* * This function is similar to a_Dw_ext_iterator_new, but is in many * cases faster, since it tries to copy parts of the stack of "base". * Used for selection, where the old and new position (which are * represented by DwExtIterator) are often quite next to each other. * "base" may be NULL. */DwExtIterator* a_Dw_ext_iterator_new_variant (DwExtIterator *base,                                              DwIterator *it){   /* todo: Not yet implemented, and actually not yet needed very much. */   return a_Dw_ext_iterator_new (it);}/* * Move iterator forward and store content in it. Returns TRUE on * success. */gboolean a_Dw_ext_iterator_next (DwExtIterator *eit){   DwIterator *it = eit->stack[eit->stack_top];   if (a_Dw_iterator_next(it)) {      if (it->content.type == DW_CONTENT_WIDGET) {         /* Widget: new iterator on stack, to search in this widget. */         eit->stack_top++;         a_List_add (eit->stack, eit->stack_top, eit->stack_max);         eit->stack[eit->stack_top] =            a_Dw_widget_iterator (it->content.data.widget, it->mask, FALSE);         return a_Dw_ext_iterator_next (eit);      } else {         /* Simply return the content of the iterartor. */         eit->content = it->content;         return TRUE;      }   } else {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -