diff options
-rw-r--r-- | dw/iterator.cc | 10 | ||||
-rw-r--r-- | dw/iterator.hh | 14 | ||||
-rw-r--r-- | dw/table.cc | 2 | ||||
-rw-r--r-- | dw/table.hh | 2 | ||||
-rw-r--r-- | dw/textblock.cc | 14 | ||||
-rw-r--r-- | dw/textblock.hh | 5 | ||||
-rw-r--r-- | dw/textblock_iterator.cc | 2 | ||||
-rwxr-xr-x | install-hyphenation | 221 | ||||
-rw-r--r-- | lout/container.cc | 64 | ||||
-rw-r--r-- | lout/container.hh | 29 | ||||
-rw-r--r-- | lout/misc.cc | 26 | ||||
-rw-r--r-- | lout/misc.hh | 29 | ||||
-rw-r--r-- | lout/object.cc | 24 | ||||
-rw-r--r-- | lout/object.hh | 30 | ||||
-rw-r--r-- | src/uicmd.cc | 15 | ||||
-rw-r--r-- | test/containers.cc | 64 |
16 files changed, 350 insertions, 201 deletions
diff --git a/dw/iterator.cc b/dw/iterator.cc index ccfc068b..c31c2706 100644 --- a/dw/iterator.cc +++ b/dw/iterator.cc @@ -37,7 +37,7 @@ Iterator::Iterator(Widget *widget, Content::Type mask, bool atEnd) this->mask = mask; } -Iterator::Iterator(Iterator &it): object::Object (), misc::Comparable () +Iterator::Iterator(Iterator &it): object::Comparable () { widget = it.widget; content = it.content; @@ -214,7 +214,7 @@ object::Object *EmptyIterator::clone () return new EmptyIterator (*this); } -int EmptyIterator::compareTo (misc::Comparable *other) +int EmptyIterator::compareTo (object::Comparable *other) { EmptyIterator *otherIt = (EmptyIterator*)other; @@ -266,7 +266,7 @@ TextIterator::TextIterator (TextIterator &it): Iterator (it) text = it.text; } -int TextIterator::compareTo (misc::Comparable *other) +int TextIterator::compareTo (object::Comparable *other) { TextIterator *otherIt = (TextIterator*)other; @@ -579,7 +579,7 @@ object::Object *DeepIterator::clone () return it; } -int DeepIterator::compareTo (misc::Comparable *other) +int DeepIterator::compareTo (object::Comparable *other) { DeepIterator *otherDeepIterator = (DeepIterator*)other; @@ -717,7 +717,7 @@ object::Object *CharIterator::clone() return cloned; } -int CharIterator::compareTo(misc::Comparable *other) +int CharIterator::compareTo(object::Comparable *other) { CharIterator *otherIt = (CharIterator*)other; int c = it->compareTo(otherIt->it); diff --git a/dw/iterator.hh b/dw/iterator.hh index a48356ef..d8a59eec 100644 --- a/dw/iterator.hh +++ b/dw/iterator.hh @@ -16,7 +16,7 @@ namespace core { * * \sa dw::core::Widget::iterator */ -class Iterator: public lout::object::Object, public lout::misc::Comparable +class Iterator: public lout::object::Comparable { protected: Iterator(Widget *widget, Content::Type mask, bool atEnd); @@ -103,7 +103,7 @@ public: EmptyIterator (Widget *widget, Content::Type mask, bool atEnd); lout::object::Object *clone(); - int compareTo(lout::misc::Comparable *other); + int compareTo(lout::object::Comparable *other); bool next (); bool prev (); void highlight (int start, int end, HighlightLayer layer); @@ -128,7 +128,7 @@ public: TextIterator (Widget *widget, Content::Type mask, bool atEnd, const char *text); - int compareTo(lout::misc::Comparable *other); + int compareTo(lout::object::Comparable *other); bool next (); bool prev (); @@ -144,7 +144,7 @@ public: * iterators do not have the limitation, that iteration is only done within * a widget, instead, child widgets are iterated through recursively. */ -class DeepIterator: public lout::object::Object, public lout::misc::Comparable +class DeepIterator: public lout::object::Comparable { private: class Stack: public lout::container::typed::Vector<Iterator> @@ -189,7 +189,7 @@ public: bool next (); bool prev (); inline DeepIterator *cloneDeepIterator() { return (DeepIterator*)clone(); } - int compareTo(lout::misc::Comparable *other); + int compareTo(lout::object::Comparable *other); /** * \brief Highlight a part of the current content. @@ -222,7 +222,7 @@ public: start, end, hpos, vpos); } }; -class CharIterator: public lout::object::Object, public lout::misc::Comparable +class CharIterator: public lout::object::Comparable { public: // START and END must not clash with any char value @@ -240,7 +240,7 @@ public: ~CharIterator (); lout::object::Object *clone(); - int compareTo(lout::misc::Comparable *other); + int compareTo(lout::object::Comparable *other); bool next (); bool prev (); diff --git a/dw/table.cc b/dw/table.cc index ee9762fe..5587f469 100644 --- a/dw/table.cc +++ b/dw/table.cc @@ -1114,7 +1114,7 @@ object::Object *Table::TableIterator::clone() return new TableIterator ((Table*)getWidget(), getMask(), index); } -int Table::TableIterator::compareTo(misc::Comparable *other) +int Table::TableIterator::compareTo(object::Comparable *other) { return index - ((TableIterator*)other)->index; } diff --git a/dw/table.hh b/dw/table.hh index 7bcc6c1b..b8feb835 100644 --- a/dw/table.hh +++ b/dw/table.hh @@ -344,7 +344,7 @@ private: TableIterator (Table *table, core::Content::Type mask, int index); lout::object::Object *clone(); - int compareTo(lout::misc::Comparable *other); + int compareTo(lout::object::Comparable *other); bool next (); bool prev (); diff --git a/dw/textblock.cc b/dw/textblock.cc index 9d61e06e..03f15f63 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -1786,9 +1786,8 @@ void Textblock::addText (const char *text, size_t len, if(i < numParts - 1) { Word *word = words->getLastRef(); - word->badnessAndPenalty - .setPenalties (penalties[partPenaltyIndex[i]][0], - penalties[partPenaltyIndex[i]][1]); + setBreakOption (word, style, penalties[partPenaltyIndex[i]][0], + penalties[partPenaltyIndex[i]][1]); if (charRemoved[i]) // Currently, only unconditional hyphens (UTF-8: @@ -1982,7 +1981,7 @@ void Textblock::addBreakOption (core::style::Style *style) { int wordIndex = words->size () - 1; if (wordIndex >= 0) { - setBreakOption (words->getRef(wordIndex), style); + setBreakOption (words->getRef(wordIndex), style, 0, 0); // Call of accumulateWordData() is not needed here. correctLastWordExtremes (); } @@ -2008,7 +2007,7 @@ void Textblock::fillSpace (Word *word, core::style::Style *style) // Do not override a previously set break penalty. if (!word->content.space) { - setBreakOption (word, style); + setBreakOption (word, style, 0, 0); word->content.space = true; word->effSpace = word->origSpace = style->font->spaceWidth + @@ -2032,7 +2031,8 @@ void Textblock::fillSpace (Word *word, core::style::Style *style) * (and so addSpace), but may be called, via addBreakOption(), as an * alternative, e. g. for ideographic characters. */ -void Textblock::setBreakOption (Word *word, core::style::Style *style) +void Textblock::setBreakOption (Word *word, core::style::Style *style, + int breakPenalty1, int breakPenalty2) { // TODO: lineMustBeBroken should be independent of the penalty // index? Otherwise, examine the last line. @@ -2041,7 +2041,7 @@ void Textblock::setBreakOption (Word *word, core::style::Style *style) case core::style::WHITE_SPACE_NORMAL: case core::style::WHITE_SPACE_PRE_LINE: case core::style::WHITE_SPACE_PRE_WRAP: - word->badnessAndPenalty.setPenalty (0); + word->badnessAndPenalty.setPenalties (breakPenalty1, breakPenalty2); break; case core::style::WHITE_SPACE_PRE: diff --git a/dw/textblock.hh b/dw/textblock.hh index f0f8347f..04a7fa68 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -384,7 +384,7 @@ protected: bool oofm, int index); lout::object::Object *clone(); - int compareTo(lout::misc::Comparable *other); + int compareTo(lout::object::Comparable *other); bool next (); bool prev (); @@ -494,7 +494,8 @@ protected: void fillWord (Word *word, int width, int ascent, int descent, short flags, core::style::Style *style); void fillSpace (Word *word, core::style::Style *style); - void setBreakOption (Word *word, core::style::Style *style); + void setBreakOption (Word *word, core::style::Style *style, + int breakPenalty1, int breakPenalty2); int textWidth (const char *text, int start, int len, core::style::Style *style, bool isStart, bool isEnd); void calcTextSize (const char *text, size_t len, core::style::Style *style, diff --git a/dw/textblock_iterator.cc b/dw/textblock_iterator.cc index 0956ef29..daf82c50 100644 --- a/dw/textblock_iterator.cc +++ b/dw/textblock_iterator.cc @@ -72,7 +72,7 @@ object::Object *Textblock::TextblockIterator::clone() new TextblockIterator ((Textblock*)getWidget(), getMask(), oofm, index); } -int Textblock::TextblockIterator::compareTo(misc::Comparable *other) +int Textblock::TextblockIterator::compareTo(object::Comparable *other) { TextblockIterator *otherTI = (TextblockIterator*)other; diff --git a/install-hyphenation b/install-hyphenation index 7ee90602..16fd0423 100755 --- a/install-hyphenation +++ b/install-hyphenation @@ -1,116 +1,153 @@ #!/usr/bin/env perl - use POSIX; use File::Basename; +use Net::FTP; + +$commondir = "language/hyph-utf8/tex/generic/hyph-utf8/patterns/txt"; + +# You may want do adjust these values. + +$host = "mirrors.dotsrc.org"; +$dir = "/ctan/$commondir"; + +#$host = "ctan.org"; +#$dir = "/tex-archive/$commondir"; -sub getpattendir () { +#$host = "ftp.dante.de"; +#$dir = "/pub/tex/$commondir"; + +$help = 0; +if (@ARGV == 0) { + $help = 1; +} else { + foreach $arg (@ARGV) { + if ($arg eq '-?' || $arg eq '--?' || $arg eq '-h' || + $arg eq '--h' || $arg eq '-help' || $arg eq '--help') { + $arg = 1; + } + } +} + +if ($help) { + print "Usage: $0 <lang1> [<lang2> ...]\n\n"; + print <<EOT; +Download and install hyphenation patterns from CTAN for different languages. +Languages are specified as defined by ISO 639-1 ("en" for English etc.). + +If there are multiple pattern files for a language (and so the filename is not +"hyph-<lang>.pat.txt"), you must specify the respective part of the filename, +e. g. "en-gb" or "en-us". In this case, the extra part ("-gb" or "-us") is +automatically removed. + +If you are not sure, simply specify the language code ("en" in this example); +you will then given a list of existing pattern files. +EOT +} else { # Extract pattern directory from Makefile, in the same directory as # this script. A complete interpretation of the Makefiles would be # too complicated, so only ${prefix} is read, which is (hopefully) # defined as constant. - - my $mf = (dirname $0) . "/Makefile", $prefix = ""; - open MF, $mf or die "Cannot open $mf for reading: $!"; + $prefix = ""; + $makefile = (dirname $0) . "/Makefile"; + open MF, $makefile or die "Cannot open $makefile: $!"; while (<MF>) { if (/^\s*prefix\s*=\s*(.*)\s*$/) { $prefix = $1; - } + } } - close MF; - + if ($prefix eq "") { - die "prefix not defined in $mf"; + die "Prefix not defined in $makefile."; } - - return "$prefix/lib/dillo/hyphenation"; -} + $patterdir = "$prefix/lib/dillo/hyphenation"; -sub printhelp { - print " Syntax: install-hyphenation <lang1> [<lang2> ...]\n"; - print "\n"; - print " If there are multiple pattern files for a language, and so the file name\n"; - print " is not \"hyph-<lang>.tex\", you can specify the origin by using a colon:\n"; - print " \"<src-lang>:<dest-lang>\", eg. \"de-1996:de\". If both are identical, the\n"; - print " colon can be committed; \"ru\" is equivalent to \"ru:ru\".\n"; - -} + if (!-e $patterdir) { + mkdir $patterdir or die "Cannot create directory $patterdir: $!"; + print "Created $patterdir.\n"; + } -sub trpatfile { - # Extract the data needed by dillo from the TeX file, based on two - # rules: - # - # 1. Extract the argument of the "\pattern" sequence, i. e. - # anything between "\pattern{" and the next "}". - # 2. As an exception, comments are always preserved. + # Connect to CTAN FTP server, change to the directory where the + # patterns lie, and read files list (which may be useful later). + $ftp = Net::FTP->new($host,Timeout=>240) + or die "Cannot connect to $host: $!"; + $ftp->login() or die "Cannot login: $!"; + $ftp->cwd($dir) or die "Cannot change to directory $dir: $!"; + @files = $ftp->ls or die "Cannot read directory: $!"; - my $url = $_[0], $in = $_[1], $out = $_[2]; - - open IN, $in or die die "Cannot open $in for reading: $!"; - open OUT, "> $out" or die "Cannot open $out for writing: $!"; - - printf OUT "%% The original file was downloaded from\n"; - printf OUT "%%\n"; - printf OUT "%% $url\n"; - printf OUT "%%\n"; - printf OUT "%% and automatically translated into this format. The original comments,\n"; - printf OUT "%% including the original copyright notice, are preserved.\n"; - printf OUT "%%\n"; - printf OUT "%% -----------------------------------------------------------------------------\n"; - printf OUT "%%\n"; - - $inpatterns = 0; - while (<IN>) { - if (/^%/) { - # Adopt all comments - print OUT; - } elsif (!$inpatterns) { - if (/\\patterns\s*{/) { - $inpatterns = 1; - } - } else { - if (/}/) { - $inpatterns = 0; - } else { - print OUT; - } + # Finally, read pattern files. + foreach $arg (@ARGV) { + if ($arg =~ /^([a-z]+)-.*$/) { + # More files per language, e. g. "en-gb". + $lang = $1; + } else { + # One file per language, e. g. "ru". + $lang = $arg; } - } - - close IN; - close OUT; + + # First, donwload the pattern file to a temporary file. + $tmppat = tmpnam(); + if ($ftp->get ("hyph-$arg.pat.txt", $tmppat)) { + printf ("Successfully downloaded pattern file for \"$arg\".\n"); + + # Search for a licence file. (Only a warning, when it does + # not exist.) + $tmplic = tmpnam(); + $licfound = 0; + if ($ftp->get ("hyph-$arg.lic.txt", $tmplic)) { + $licfound = 1; + } else { + print "Warning: Cannot download license file for \"$arg\": $!\n"; + } + + # Combine both, licence and pattern, to the final pattern + # file. + $outfile = "$patterdir/$lang.pat"; + open OUT, "> $outfile" or die "Cannot open $outfile: $!"; + + if ($licfound) { + print OUT + "% Licence from ftp://$host$dir/hyph-$arg.lic.txt\n"; + print OUT "%\n"; + open IN, $tmplic or die "Cannot open $tmplic: $!"; + while (<IN>) { + # Each line from the licence file must be a comment. + if (!/^%/) { + print OUT "% "; + } + print OUT; + } + close IN; + unlink $tmplic; - printf "Wrote pattern file: $out\n"; -} - -sub dlpatfile { - my $lang = $_[0], $destdir = $_[1], $lang1, $lang2; - if ($lang =~ /(.*):(.*)/) { - $lang1 = $1; - $lang2 = $2; - } else { - $lang1 = $lang2 = $lang; + print OUT "%\n"; + } + + print OUT "% Patterns from ftp://$host$dir/hyph-$arg.pat.txt\n"; + print OUT "%\n"; + open IN, $tmppat or die "Cannot open $tmppat: $!"; + while (<IN>) { + print OUT; + } + close IN; + unlink $tmppat; + + close OUT; + } else { + # Not found. If a single language was specified (e. g. "en"), + # search for possibilities. + print "Error: Cannot download pattern file for \"$arg\": $!\n"; + if ($lang eq $arg) { + print "Try one of these:\n"; + foreach(@files) { + if (/^hyph-($lang-.*)\.pat\.txt$/) { + print " $1\n"; + } + } + } + } } - my $url = "ftp://ftp.mpi-sb.mpg.de/pub/tex/mirror/ftp.dante.de/pub/tex/language/hyph-utf8/tex/generic/hyph-utf8/patterns/tex/hyph-$lang1.tex"; - my $tmp = tmpnam(); - if (system("wget -O $tmp $url") == 0) { - my $out = "$destdir/$lang2.pat"; - trpatfile $url, $tmp, $out; - unlink $tmp; - } else { - print "Error downloading patterns for language $lang1. See messages above for details.\n" - } -} - -$destdir = getpattendir; - -foreach $lang (@ARGV) { - if ($lang eq '-?' || $lang eq '--?' || $lang eq '-h' || - $lang eq '--h' || $lang eq '-help' || $lang eq '--help') { - printhelp; - } else { - dlpatfile $lang, $destdir; - } + $ftp->quit; } diff --git a/lout/container.cc b/lout/container.cc index deeede57..5e5eda73 100644 --- a/lout/container.cc +++ b/lout/container.cc @@ -190,16 +190,72 @@ void Vector::remove(int pos) */ void Vector::sort() { - qsort(array, numElements, sizeof(Object*), misc::Comparable::compareFun); + qsort (array, numElements, sizeof(Object*), Comparable::compareFun); } - /** - * \bug Not implemented. + * \brief Use binary search to find an element in a sorted vector. + * + * If "mustExist" is true, only exact matches are found; otherwise, -1 + * is returned. If it is false, the position of the next greater + * element is returned, or, if the key is the greatest element, the + * size of the array. (This is the value which can be used for + * insertion; see insertSortet()). */ +int Vector::bsearch(Object *key, bool mustExist) +{ + // The case !mustExist is not handled by bsearch(3), so here is a + // new implementation. + + int high = numElements - 1, low = 0; + + while (true) { + int index = (low + high) / 2; + int c = ((Comparable*) key)->compareTo ((Comparable*)array[index]); + if (c == 0) + return index; + else { + if (low >= high) { + if (mustExist) + return -1; + else + return c > 0 ? index + 1 : index; + } + + if (c < 0) + high = index - 1; + else + low = index + 1; + } + } + + + /* + void *result = ::bsearch (&key, array, numElements, sizeof (Object*), + Comparable::compareFun); + if (result) + return (Object**)result - array; + else + return -1; + */ +} + +Object *Vector::VectorIterator::getNext() +{ + if (index < vector->numElements - 1) + index++; + + return index < vector->numElements ? vector->array[index] : NULL; +} + +bool Vector::VectorIterator::hasNext() +{ + return index < vector->numElements - 1; +} + Collection0::AbstractIterator* Vector::createIterator() { - return NULL; + return new VectorIterator(this); } // ------------ diff --git a/lout/container.hh b/lout/container.hh index f1008e82..c87eb10c 100644 --- a/lout/container.hh +++ b/lout/container.hh @@ -102,11 +102,25 @@ public: */ class Vector: public Collection { + friend class VectorIterator; + private: object::Object **array; int numAlloc, numElements; bool ownerOfObjects; + class VectorIterator: public AbstractIterator + { + private: + Vector *vector; + int index; + + public: + VectorIterator(Vector *vector) { this->vector = vector; index = -1; } + bool hasNext(); + Object *getNext(); + }; + protected: AbstractIterator* createIterator(); @@ -116,12 +130,23 @@ public: void put(object::Object *newElement, int newPos = -1); void insert(object::Object *newElement, int pos); + + /** + * \brief Insert into an already sorted vector. + * + * Notice that insertion is not very efficient, unless the position + * is rather at the end. + */ + inline void insertSorted(object::Object *newElement) + { insert (newElement, bsearch (newElement, false)); } + void remove(int pos); inline object::Object *get(int pos) { return (pos >= 0 && pos < numElements) ? array[pos] : NULL; } inline int size() { return numElements; } void clear(); void sort(); + int bsearch(Object *key, bool mustExist); }; @@ -381,12 +406,16 @@ public: { ((untyped::Vector*)this->base)->put(newElement, newPos); } inline void insert(T *newElement, int pos) { ((untyped::Vector*)this->base)->insert(newElement, pos); } + inline void insertSorted(T *newElement) + { ((untyped::Vector*)this->base)->insertSorted(newElement); } inline void remove(int pos) { ((untyped::Vector*)this->base)->remove(pos); } inline T *get(int pos) { return (T*)((untyped::Vector*)this->base)->get(pos); } inline int size() { return ((untyped::Vector*)this->base)->size(); } inline void clear() { ((untyped::Vector*)this->base)->clear(); } inline void sort() { ((untyped::Vector*)this->base)->sort(); } + inline int bsearch(T *key, bool mustExist) + { return ((untyped::Vector*)this->base)->bsearch(key, mustExist); } }; diff --git a/lout/misc.cc b/lout/misc.cc index f45a3450..d4db609e 100644 --- a/lout/misc.cc +++ b/lout/misc.cc @@ -37,32 +37,6 @@ void init (int argc, char *argv[]) prgName = strdup (argv[0]); } -// ---------------- -// Comparable -// ---------------- - -Comparable::~Comparable() -{ -} - -/** - * \brief This static method may be used as compare function for qsort(3), for - * an array of Object* (Object*[] or Object**). - */ -int Comparable::compareFun(const void *p1, const void *p2) -{ - Comparable **c1 = (Comparable**)p1; - Comparable **c2 = (Comparable**)p2; - if (c1 && c2) - return ((*c1)->compareTo(*c2)); - else if (c1) - return 1; - else if (c2) - return -1; - else - return 0; -} - // ------------------ // StringBuffer diff --git a/lout/misc.hh b/lout/misc.hh index b0c0b2f8..cff8e05b 100644 --- a/lout/misc.hh +++ b/lout/misc.hh @@ -65,35 +65,6 @@ inline int AsciiStrcasecmp(const char *s1, const char *s2) } /** - * \brief Instances of a sub class of this interface may be compared (less, - * greater). - * - * Used for sorting etc. - */ -class Comparable -{ -public: - virtual ~Comparable(); - - /** - * \brief Compare two objects c1 and c2. - * - * return a value < 0, when c1 is less than c2, a value > 0, when c1 - * is greater than c2, or 0, when c1 and c2 are equal. - * - * If also object::Object is implemented, and if c1.equals(c2), - * c1.compareTo(c2) must be 0, but, unlike you may expect, - * the reversed is not necessarily true. This method returns 0, if, - * according to the rules for sorting, there is no difference, but there - * may still be differences (not relevant for sorting), which "equals" will - * care about. - */ - virtual int compareTo(Comparable *other) = 0; - - static int compareFun(const void *p1, const void *p2); -}; - -/** * \brief Simple (simpler than container::untyped::Vector and * container::typed::Vector) template based vector. */ diff --git a/lout/object.cc b/lout/object.cc index 85a908b9..99b5902d 100644 --- a/lout/object.cc +++ b/lout/object.cc @@ -106,6 +106,30 @@ size_t Object::sizeOf() return sizeof(Object*); } +// ---------------- +// Comparable +// ---------------- + +/** + * \brief This static method may be used as compare function for + * qsort(3) and bsearch(3), for an array of Object* (Object*[] or + * Object**). + */ +int Comparable::compareFun(const void *p1, const void *p2) +{ + Comparable *c1 = *(Comparable**)p1; + Comparable *c2 = *(Comparable**)p2; + + if (c1 && c2) + return ((c1)->compareTo(c2)); + else if (c1) + return 1; + else if (c2) + return -1; + else + return 0; +} + // ------------- // Pointer // ------------- diff --git a/lout/object.hh b/lout/object.hh index 9df69987..fd612863 100644 --- a/lout/object.hh +++ b/lout/object.hh @@ -34,6 +34,32 @@ public: }; /** + * \brief Instances of a sub class of may be compared (less, greater). + * + * Used for sorting etc. + */ +class Comparable: public Object +{ +public: + /** + * \brief Compare two objects c1 and c2. + * + * Return a value < 0, when c1 is less than c2, a value > 0, when c1 + * is greater than c2, or 0, when c1 and c2 are equal. + * + * If c1.equals(c2) (as defined in Object), c1.compareTo(c2) must + * be 0, but, unlike you may expect, the reversed is not + * necessarily true. This method returns 0, if, according to the + * rules for sorting, there is no difference, but there may still + * be differences (not relevant for sorting), which "equals" will + * care about. + */ + virtual int compareTo(Comparable *other) = 0; + + static int compareFun(const void *p1, const void *p2); +}; + +/** * \brief An object::Object wrapper for void pointers. */ class Pointer: public Object @@ -63,7 +89,7 @@ public: /** * \brief An object::Object wrapper for int's. */ -class Integer: public Object, misc::Comparable +class Integer: public Comparable { int value; @@ -82,7 +108,7 @@ public: * * As opposed to object::String, the char array is not copied. */ -class ConstString: public Object, misc::Comparable +class ConstString: public Comparable { protected: const char *str; diff --git a/src/uicmd.cc b/src/uicmd.cc index 153d5fb4..f08c7e70 100644 --- a/src/uicmd.cc +++ b/src/uicmd.cc @@ -901,17 +901,10 @@ static int UIcmd_save_file_check(const char *name) static void UIcmd_save(BrowserWindow *bw, const DilloUrl *url, const char *title) { - const char *name; - bool_t first_prompt = 1; + char *SuggestedName = UIcmd_make_save_filename(url); + while (1) { - char *SuggestedName; - - SuggestedName = - first_prompt - ? UIcmd_make_save_filename(url) - : dStrdup(name); - first_prompt = 0; - name = a_Dialog_save_file(title, NULL, SuggestedName); + const char *name = a_Dialog_save_file(title, NULL, SuggestedName); dFree(SuggestedName); if (name) { @@ -932,6 +925,8 @@ static void UIcmd_save(BrowserWindow *bw, const DilloUrl *url, } else { return; /* no name, so Abort */ } + + SuggestedName = dStrdup(name); } } diff --git a/test/containers.cc b/test/containers.cc index 646624aa..d8107bdf 100644 --- a/test/containers.cc +++ b/test/containers.cc @@ -6,41 +6,76 @@ using namespace lout::container::typed; void testHashSet () { + puts ("--- testHashSet ---"); + HashSet<String> h(true); h.put (new String ("one")); h.put (new String ("two")); h.put (new String ("three")); - Iterator<String> it = h.iterator (); - while (it.hasNext ()) { - String *o = it.getNext (); - printf ("%s\n", o->chars()); - } + puts (h.toString()); } void testHashTable () { + puts ("--- testHashTable ---"); + HashTable<String, Integer> h(true, true); h.put (new String ("one"), new Integer (1)); h.put (new String ("two"), new Integer (2)); h.put (new String ("three"), new Integer (3)); - for (Iterator<String> it = h.iterator (); it.hasNext (); ) { - String *k = it.getNext (); - Integer *v = h.get (k); - printf ("%s -> %d\n", k->chars(), v->getValue()); - } + puts (h.toString()); h.put (new String ("one"), new Integer (4)); h.put (new String ("two"), new Integer (5)); h.put (new String ("three"), new Integer (6)); + + puts (h.toString()); +} + +void testVector () +{ + puts ("--- testVector ---"); + + Vector<String> v (true, 1); + + v.put (new String ("one")); + v.put (new String ("two")); + v.put (new String ("three")); + puts (v.toString()); + + v.sort (); + puts (v.toString()); + + v.insertSorted (new String ("five")); + puts (v.toString()); + + v.insertSorted (new String ("six")); + puts (v.toString()); + + v.insertSorted (new String ("four")); + puts (v.toString()); + + for (int b = 0; b < 2; b++) { + bool mustExist = b; + printf ("mustExist = %s\n", mustExist ? "true" : "false"); - for (Iterator<String> it = h.iterator (); it.hasNext (); ) { - String *k = it.getNext (); - Integer *v = h.get (k); - printf ("%s -> %d\n", k->chars(), v->getValue()); + String k ("alpha"); + printf (" '%s' -> %d\n", k.chars(), v.bsearch (&k, mustExist)); + + for (Iterator<String> it = v.iterator(); it.hasNext(); ) { + String *k1 = it.getNext(); + printf (" '%s' -> %d\n", k1->chars(), v.bsearch (k1, mustExist)); + + char buf[64]; + strcpy (buf, k1->chars()); + strcat (buf, "-var"); + String k2 (buf); + printf (" '%s' -> %d\n", k2.chars(), v.bsearch (&k2, mustExist)); + } } } @@ -48,6 +83,7 @@ int main (int argc, char *argv[]) { testHashSet (); testHashTable (); + testVector (); return 0; } |