From d25d58214567928fe15016f49b3be819aca0703f Mon Sep 17 00:00:00 2001
From: Dimitri van Heesch <dimitri@stack.nl>
Date: Sun, 26 Oct 2003 21:03:52 +0000
Subject: Release-1.3.4-20031026

---
 INSTALL                   |   4 +-
 Makefile.in               |   7 +-
 Makefile.win_make.in      |   1 +
 Makefile.win_nmake.in     |   3 +
 README                    |   4 +-
 VERSION                   |   2 +-
 configure                 |   5 +-
 libmd5/Makefile.in        |  16 ++
 libmd5/libmd5.pro.in      |  10 +
 libmd5/md5.c              | 565 ++++++++++++++++++++++++++++++++++++++++++++++
 libmd5/md5.h              | 225 ++++++++++++++++++
 libmd5/md5_loc.h          | 106 +++++++++
 packages/rpm/doxygen.spec |   2 +-
 src/dot.cpp               | 406 ++++++++++++++++++++-------------
 src/dot.h                 |  18 +-
 src/doxygen.pro.in        |  14 +-
 src/htmlgen.cpp           |   2 +-
 src/index.cpp             |   4 +-
 src/latexdocvisitor.cpp   |  10 +-
 src/libdoxygen.pro.in     |   1 +
 src/mandocvisitor.cpp     |   2 +
 src/rtfdocvisitor.cpp     |   3 +-
 src/scanner.l             | 173 ++++++++++++--
 src/search.php            |   4 +
 src/search_php.h          |   4 +
 src/translator_kr.h       |   2 +-
 26 files changed, 1386 insertions(+), 207 deletions(-)
 create mode 100644 libmd5/Makefile.in
 create mode 100644 libmd5/libmd5.pro.in
 create mode 100644 libmd5/md5.c
 create mode 100644 libmd5/md5.h
 create mode 100644 libmd5/md5_loc.h

diff --git a/INSTALL b/INSTALL
index 1380346..a2f15a9 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
-DOXYGEN Version 1.3.4-20031019
+DOXYGEN Version 1.3.4-20031026
 
 Please read the installation section of the manual 
 (http://www.doxygen.org/install.html) for instructions.
 
 --------
-Dimitri van Heesch (19 October 2003)
+Dimitri van Heesch (26 October 2003)
diff --git a/Makefile.in b/Makefile.in
index 3a07b16..f668893 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -8,6 +8,7 @@ clean: FORCE
 	cd qtools ; $(MAKE) clean
 	cd src ; $(MAKE) clean
 	cd libpng ; $(MAKE) clean
+	cd libmd5 ; $(MAKE) clean
 	cd addon/doxywizard ; $(MAKE) clean
 	cd addon/doxmlparser/src ; $(MAKE) clean
 	cd addon/doxmlparser/test ; $(MAKE) clean
@@ -18,6 +19,7 @@ clean: FORCE
 distclean: clean
 	cd src ; $(MAKE) distclean
 	cd libpng ; $(MAKE) distclean
+	cd libmd5 ; $(MAKE) distclean
 	cd addon/doxywizard ; $(MAKE) distclean
 	cd addon/doxmlparser/src ; $(MAKE) distclean
 	cd addon/doxmlparser/test ; $(MAKE) distclean
@@ -30,9 +32,10 @@ distclean: clean
 	-rm -f src/Makefile.doxygen src/Makefile.libdoxygen 
 	-rm -f src/Makefile.doxytag src/Makefile.libdoxycfg
 	-rm -f libpng/Makefile.libpng
+	-rm -f libmd5/Makefile.libmd5
 	-rm -f Makefile qtools/Makefile src/Makefile examples/Makefile doc/Makefile 
 	-rm -f .makeconfig .tmakeconfig
-	-rm -f src/doxygen.pro src/libdoxygen.pro src/doxytag.pro qtools/qtools.pro src/libdoxycfg.pro libpng/libpng.pro
+	-rm -f src/doxygen.pro src/libdoxygen.pro src/doxytag.pro qtools/qtools.pro src/libdoxycfg.pro libpng/libpng.pro libmd5/libmd5.pro
 	-rm -f src/version.cpp
 	-rm -r addon/doxywizard/Makefile
 	-rm -f addon/doxywizard/Makefile.doxywizard
@@ -71,7 +74,7 @@ pdf: docs
 	cd latex ; $(MAKE)
 
 archive: clean
-	tar zcvf dx`date +%y%m%d`.tgz Doxyfile libpng addon tmake doc wintools examples bin lib objects \
+	tar zcvf dx`date +%y%m%d`.tgz Doxyfile libpng libmd5 addon tmake doc wintools examples bin lib objects \
 	       qtools src configure configure.bin Makefile.in Makefile.win_nmake.in \
                Makefile.win_make.in INSTALL make.bat LANGUAGE.HOWTO LICENSE PLATFORMS \
                VERSION packages
diff --git a/Makefile.win_make.in b/Makefile.win_make.in
index 17c93a9..8635696 100644
--- a/Makefile.win_make.in
+++ b/Makefile.win_make.in
@@ -1,6 +1,7 @@
 all: src\version.cpp
 	set TMAKEPATH=$(TMAKEPATH) & cd qtools & $(MAKE)
 	set TMAKEPATH=$(TMAKEPATH) & cd libpng & $(MAKE)
+	set TMAKEPATH=$(TMAKEPATH) & cd libmd5 & $(MAKE)
 	set TMAKEPATH=$(TMAKEPATH) & cd src & $(MAKE)
 
 clean:
diff --git a/Makefile.win_nmake.in b/Makefile.win_nmake.in
index 4a2ff78..d618b6c 100644
--- a/Makefile.win_nmake.in
+++ b/Makefile.win_nmake.in
@@ -6,6 +6,9 @@ all: src\version.cpp
 	cd libpng
 	$(MAKE)
 	cd ..
+	cd libmd5
+	$(MAKE)
+	cd ..
 	cd src 
 	$(MAKE)
 
diff --git a/README b/README
index 1b1dc93..84a1061 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-DOXYGEN Version 1.3.4_20031019
+DOXYGEN Version 1.3.4_20031026
 
 Please read INSTALL for compilation instructions.
 
@@ -17,4 +17,4 @@ to subscribe to the lists or to visit the archives.
 
 Enjoy,
 
-Dimitri van Heesch (dimitri@stack.nl) (19 October 2003)
+Dimitri van Heesch (dimitri@stack.nl) (26 October 2003)
diff --git a/VERSION b/VERSION
index a5dbbe7..00a63fb 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.3.4-20031019
+1.3.4-20031026
diff --git a/configure b/configure
index 0afd55c..df7b481 100755
--- a/configure
+++ b/configure
@@ -427,7 +427,7 @@ TMAKE_CXXFLAGS += -DENGLISH_ONLY
 EOF
 fi
 
-f_inmakefiles="Makefile.in qtools/Makefile.in src/Makefile.in examples/Makefile.in doc/Makefile.in addon/doxywizard/Makefile.in addon/doxmlparser/src/Makefile.in addon/doxmlparser/test/Makefile.in addon/doxmlparser/examples/metrics/Makefile.in libpng/Makefile.in"
+f_inmakefiles="Makefile.in qtools/Makefile.in src/Makefile.in examples/Makefile.in doc/Makefile.in addon/doxywizard/Makefile.in addon/doxmlparser/src/Makefile.in addon/doxmlparser/test/Makefile.in addon/doxmlparser/examples/metrics/Makefile.in libpng/Makefile.in libmd5/Makefile.in"
 
 for i in $f_inmakefiles ; do
      SRC=$i
@@ -445,6 +445,7 @@ EOF
        echo "all: src/version.cpp " >> $DST
        echo "	\$(MAKE) -C qtools" >> $DST
        echo "	\$(MAKE) -C libpng" >> $DST
+       echo "	\$(MAKE) -C libmd5" >> $DST
        echo "	\$(MAKE) -C src" >> $DST
        if test $f_wizard = YES; then
          echo "	\$(MAKE) -C addon/doxywizard" >> $DST
@@ -460,7 +461,7 @@ EOF
      echo "  Created $DST from $SRC..."
 done
 
-f_inprofiles="qtools/qtools.pro.in src/libdoxygen.pro.in src/libdoxycfg.pro.in src/doxygen.pro.in src/doxytag.pro.in addon/doxywizard/doxywizard.pro.in addon/doxmlparser/src/doxmlparser.pro.in addon/doxmlparser/test/xmlparse.pro.in addon/doxmlparser/examples/metrics/metrics.pro.in libpng/libpng.pro.in" 
+f_inprofiles="qtools/qtools.pro.in src/libdoxygen.pro.in src/libdoxycfg.pro.in src/doxygen.pro.in src/doxytag.pro.in addon/doxywizard/doxywizard.pro.in addon/doxmlparser/src/doxmlparser.pro.in addon/doxmlparser/test/xmlparse.pro.in addon/doxmlparser/examples/metrics/metrics.pro.in libpng/libpng.pro.in libmd5/libmd5.pro.in" 
 
 for i in $f_inprofiles ; do
      SRC=$i
diff --git a/libmd5/Makefile.in b/libmd5/Makefile.in
new file mode 100644
index 0000000..5f71b11
--- /dev/null
+++ b/libmd5/Makefile.in
@@ -0,0 +1,16 @@
+all: Makefile.libmd5 
+	$(MAKE) -f Makefile.libmd5
+
+clean: Makefile.libmd5 
+	$(MAKE) -f Makefile.libmd5 clean
+
+distclean: clean
+	$(RM) -f Makefile.libmd5 libmd5.pro Makefile 
+
+tmake:
+	$(ENV) $(PERL) $(TMAKE) libmd5.pro >Makefile.libmd5
+
+Makefile.libmd5: libmd5.pro
+	$(ENV) $(PERL) $(TMAKE) libmd5.pro >Makefile.libmd5
+
+install:
diff --git a/libmd5/libmd5.pro.in b/libmd5/libmd5.pro.in
new file mode 100644
index 0000000..8cf7118
--- /dev/null
+++ b/libmd5/libmd5.pro.in
@@ -0,0 +1,10 @@
+TEMPLATE	= lib
+CONFIG		= warn_on staticlib $extraopts
+HEADERS		= md5.h md5_loc.h
+SOURCES		= md5.c
+win32:INCLUDEPATH          += .
+win32-g++:TMAKE_CFLAGS     += -D__CYGWIN__ -DALL_STATIC
+DESTDIR                    =  ../lib
+TARGET                     =  md5
+OBJECTS_DIR                =  ../objects
+
diff --git a/libmd5/md5.c b/libmd5/md5.c
new file mode 100644
index 0000000..a667090
--- /dev/null
+++ b/libmd5/md5.c
@@ -0,0 +1,565 @@
+/*
+ * Functions to compute MD5 message digest of files or memory blocks
+ * according to the definition of MD5 in RFC 1321 from April 1992.
+ * Copyright (C) 1995, 1996 Free Software Foundation, Inc.  NOTE: The
+ * canonical source of this file is maintained with the GNU C Library.
+ * Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+ *
+ * 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, 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.
+ *
+ * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ * Modified by Gray Watson <http://256.com/gray/>, 1997.
+ *
+ * $Id$
+ */
+
+/*
+ * NOTE: during quick performance tests on a Sun Sparc Ultra 1 and an
+ * Alpha 255 300, these functions performed upwards of 3mb/sec
+ * including disk I/O time.
+ */
+
+/*
+ * MD5 Test Suite from RFC1321: http://ds.internic.net:/rfc/rfc1321.txt
+ *
+ * MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
+ * MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
+ * MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
+ * MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
+ * MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
+ * MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
+ * d174ab98d277d9f5a5611c2c9f419d9f
+ * MD5 ("123456789012345678901234567890123456789012345678901234567890123456
+ * 78901234567890") = 57edf4a22be3c955ac49da2e2107b67a
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "md5.h"
+#include "md5_loc.h"
+
+#if LIB_VERSION_REQUIRED
+static	char	*rcs_id =
+  "$Id$";
+
+/* version id for the library */
+static char *version_id = "$MD5Version: 1.0.0 November-19-1997 $";
+#endif
+
+/****************************** local routines *******************************/
+
+/*
+ * process_block
+ *
+ * DESCRIPTION:
+ *
+ * Process a block of bytes into a MD5 state structure.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * md5_p - Pointer to MD5 structure from which we are getting the result.
+ *
+ * buffer - A buffer of bytes whose MD5 signature we are calculating.
+ *
+ * buf_len - The length of the buffer.
+ */
+static	void	process_block(md5_t *md5_p, const void *buffer,
+			      const unsigned int buf_len)
+{
+  md5_uint32	correct[16];
+  const void	*buf_p = buffer, *end_p;
+  unsigned int	words_n;
+  md5_uint32	A, B, C, D;
+
+  words_n = buf_len / sizeof(md5_uint32);
+  end_p = (char *)buf_p + words_n * sizeof(md5_uint32);
+
+  A = md5_p->md_A;
+  B = md5_p->md_B;
+  C = md5_p->md_C;
+  D = md5_p->md_D;
+
+  /*
+   * First increment the byte count.  RFC 1321 specifies the possible
+   * length of the file up to 2^64 bits.  Here we only compute the
+   * number of bytes with a double word increment.  Modified to do
+   * this to better avoid overflows in the lower word -- Gray 10/97.
+   */
+  if (md5_p->md_total[0] > MAX_MD5_UINT32 - buf_len) {
+    md5_p->md_total[1]++;
+    md5_p->md_total[0] -= (MAX_MD5_UINT32 - buf_len);
+  }
+  else {
+    md5_p->md_total[0] += buf_len;
+  }
+
+  /*
+   * Process all bytes in the buffer with MD5_BLOCK bytes in each
+   * round of the loop.
+   */
+  while (buf_p < end_p) {
+    md5_uint32	A_save, B_save, C_save, D_save;
+    md5_uint32	*corr_p = correct;
+
+    A_save = A;
+    B_save = B;
+    C_save = C;
+    D_save = D;
+
+    /*
+     * Before we start, one word to the strange constants.  They are
+     * defined in RFC 1321 as
+     *
+     * T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..MD5_BLOCK
+     */
+
+    /* Round 1. */
+    OP1 (A, B, C, D, buf_p, corr_p,  7, 0xd76aa478);
+    OP1 (D, A, B, C, buf_p, corr_p, 12, 0xe8c7b756);
+    OP1 (C, D, A, B, buf_p, corr_p, 17, 0x242070db);
+    OP1 (B, C, D, A, buf_p, corr_p, 22, 0xc1bdceee);
+    OP1 (A, B, C, D, buf_p, corr_p,  7, 0xf57c0faf);
+    OP1 (D, A, B, C, buf_p, corr_p, 12, 0x4787c62a);
+    OP1 (C, D, A, B, buf_p, corr_p, 17, 0xa8304613);
+    OP1 (B, C, D, A, buf_p, corr_p, 22, 0xfd469501);
+    OP1 (A, B, C, D, buf_p, corr_p,  7, 0x698098d8);
+    OP1 (D, A, B, C, buf_p, corr_p, 12, 0x8b44f7af);
+    OP1 (C, D, A, B, buf_p, corr_p, 17, 0xffff5bb1);
+    OP1 (B, C, D, A, buf_p, corr_p, 22, 0x895cd7be);
+    OP1 (A, B, C, D, buf_p, corr_p,  7, 0x6b901122);
+    OP1 (D, A, B, C, buf_p, corr_p, 12, 0xfd987193);
+    OP1 (C, D, A, B, buf_p, corr_p, 17, 0xa679438e);
+    OP1 (B, C, D, A, buf_p, corr_p, 22, 0x49b40821);
+
+    /* Round 2. */
+    OP234 (FG, A, B, C, D, correct[  1],  5, 0xf61e2562);
+    OP234 (FG, D, A, B, C, correct[  6],  9, 0xc040b340);
+    OP234 (FG, C, D, A, B, correct[ 11], 14, 0x265e5a51);
+    OP234 (FG, B, C, D, A, correct[  0], 20, 0xe9b6c7aa);
+    OP234 (FG, A, B, C, D, correct[  5],  5, 0xd62f105d);
+    OP234 (FG, D, A, B, C, correct[ 10],  9, 0x02441453);
+    OP234 (FG, C, D, A, B, correct[ 15], 14, 0xd8a1e681);
+    OP234 (FG, B, C, D, A, correct[  4], 20, 0xe7d3fbc8);
+    OP234 (FG, A, B, C, D, correct[  9],  5, 0x21e1cde6);
+    OP234 (FG, D, A, B, C, correct[ 14],  9, 0xc33707d6);
+    OP234 (FG, C, D, A, B, correct[  3], 14, 0xf4d50d87);
+    OP234 (FG, B, C, D, A, correct[  8], 20, 0x455a14ed);
+    OP234 (FG, A, B, C, D, correct[ 13],  5, 0xa9e3e905);
+    OP234 (FG, D, A, B, C, correct[  2],  9, 0xfcefa3f8);
+    OP234 (FG, C, D, A, B, correct[  7], 14, 0x676f02d9);
+    OP234 (FG, B, C, D, A, correct[ 12], 20, 0x8d2a4c8a);
+
+    /* Round 3. */
+    OP234 (FH, A, B, C, D, correct[  5],  4, 0xfffa3942);
+    OP234 (FH, D, A, B, C, correct[  8], 11, 0x8771f681);
+    OP234 (FH, C, D, A, B, correct[ 11], 16, 0x6d9d6122);
+    OP234 (FH, B, C, D, A, correct[ 14], 23, 0xfde5380c);
+    OP234 (FH, A, B, C, D, correct[  1],  4, 0xa4beea44);
+    OP234 (FH, D, A, B, C, correct[  4], 11, 0x4bdecfa9);
+    OP234 (FH, C, D, A, B, correct[  7], 16, 0xf6bb4b60);
+    OP234 (FH, B, C, D, A, correct[ 10], 23, 0xbebfbc70);
+    OP234 (FH, A, B, C, D, correct[ 13],  4, 0x289b7ec6);
+    OP234 (FH, D, A, B, C, correct[  0], 11, 0xeaa127fa);
+    OP234 (FH, C, D, A, B, correct[  3], 16, 0xd4ef3085);
+    OP234 (FH, B, C, D, A, correct[  6], 23, 0x04881d05);
+    OP234 (FH, A, B, C, D, correct[  9],  4, 0xd9d4d039);
+    OP234 (FH, D, A, B, C, correct[ 12], 11, 0xe6db99e5);
+    OP234 (FH, C, D, A, B, correct[ 15], 16, 0x1fa27cf8);
+    OP234 (FH, B, C, D, A, correct[  2], 23, 0xc4ac5665);
+
+    /* Round 4. */
+    OP234 (FI, A, B, C, D, correct[  0],  6, 0xf4292244);
+    OP234 (FI, D, A, B, C, correct[  7], 10, 0x432aff97);
+    OP234 (FI, C, D, A, B, correct[ 14], 15, 0xab9423a7);
+    OP234 (FI, B, C, D, A, correct[  5], 21, 0xfc93a039);
+    OP234 (FI, A, B, C, D, correct[ 12],  6, 0x655b59c3);
+    OP234 (FI, D, A, B, C, correct[  3], 10, 0x8f0ccc92);
+    OP234 (FI, C, D, A, B, correct[ 10], 15, 0xffeff47d);
+    OP234 (FI, B, C, D, A, correct[  1], 21, 0x85845dd1);
+    OP234 (FI, A, B, C, D, correct[  8],  6, 0x6fa87e4f);
+    OP234 (FI, D, A, B, C, correct[ 15], 10, 0xfe2ce6e0);
+    OP234 (FI, C, D, A, B, correct[  6], 15, 0xa3014314);
+    OP234 (FI, B, C, D, A, correct[ 13], 21, 0x4e0811a1);
+    OP234 (FI, A, B, C, D, correct[  4],  6, 0xf7537e82);
+    OP234 (FI, D, A, B, C, correct[ 11], 10, 0xbd3af235);
+    OP234 (FI, C, D, A, B, correct[  2], 15, 0x2ad7d2bb);
+    OP234 (FI, B, C, D, A, correct[  9], 21, 0xeb86d391);
+
+    /* Add the starting values of the context. */
+    A += A_save;
+    B += B_save;
+    C += C_save;
+    D += D_save;
+  }
+
+  /* Put checksum in context given as argument. */
+  md5_p->md_A = A;
+  md5_p->md_B = B;
+  md5_p->md_C = C;
+  md5_p->md_D = D;
+}
+
+/*
+ * md5_get_result
+ *
+ * DESCRIPTION:
+ *
+ * Copy the resulting MD5 signature from MD5_P into the first 16 bytes
+ * (MD5_SIZE) of the result buffer.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * md5_p - Pointer to MD5 structure from which we are getting the result.
+ *
+ * result - A 16 byte buffer that will contain the MD5 signature.
+ */
+static	void	md5_get_result(const md5_t *md5_p, void *result)
+{
+  md5_uint32	hold;
+  void		*res_p = result;
+
+  hold = SWAP(md5_p->md_A);
+  memcpy(res_p, &hold, sizeof(md5_uint32));
+  res_p = (char *)res_p + sizeof(md5_uint32);
+
+  hold = SWAP(md5_p->md_B);
+  memcpy(res_p, &hold, sizeof(md5_uint32));
+  res_p = (char *)res_p + sizeof(md5_uint32);
+
+  hold = SWAP(md5_p->md_C);
+  memcpy(res_p, &hold, sizeof(md5_uint32));
+  res_p = (char *)res_p + sizeof(md5_uint32);
+
+  hold = SWAP(md5_p->md_D);
+  memcpy(res_p, &hold, sizeof(md5_uint32));
+}
+
+/***************************** exported routines *****************************/
+
+/*
+ * md5_init
+ *
+ * DESCRIPTION:
+ *
+ * Initialize structure containing state of MD5 computation. (RFC 1321,
+ * 3.3: Step 3).  This is for progressive MD5 calculations only.  If
+ * you have the complete string available, md5_buffer should be used.
+ * md5_process should be called for each bunch of bytes and after the
+ * last process call, md5_finish should be called to get the
+ * signature.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * md5_p - Pointer to md5 structure that we are initializing.
+ */
+void	md5_init(md5_t *md5_p)
+{
+  md5_p->md_A = 0x67452301;
+  md5_p->md_B = 0xefcdab89;
+  md5_p->md_C = 0x98badcfe;
+  md5_p->md_D = 0x10325476;
+
+  md5_p->md_total[0] = 0;
+  md5_p->md_total[1] = 0;
+  md5_p->md_buf_len = 0;
+}
+
+/*
+ * md5_process
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to progressively calculate a MD5 signature some
+ * number of bytes at a time.  If you have the complete string
+ * available, md5_buffer should be used.  The MD5 structure should
+ * have been initialized with md5_init and after the last process
+ * call, md5_finish should be called to get the results.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * md5_p - Pointer to MD5 structure which we are progressively updating.
+ *
+ * buffer - A buffer of bytes whose MD5 signature we are calculating.
+ *
+ * buf_len - The length of the buffer.
+ */
+void	md5_process(md5_t *md5_p, const void *buffer,
+		    const unsigned int buf_len)
+{
+  unsigned int	len = buf_len;
+  unsigned int	in_block, add;
+
+  /*
+   * When we already have some bytes in our internal buffer, copy some
+   * from the user to fill the block.
+   */
+  if (md5_p->md_buf_len > 0) {
+    
+    in_block = md5_p->md_buf_len;
+    if (in_block + len > sizeof(md5_p->md_buffer)) {
+      add = sizeof(md5_p->md_buffer) - in_block;
+    }
+    else {
+      add = len;
+    }
+
+    memcpy (md5_p->md_buffer + in_block, buffer, add);
+    md5_p->md_buf_len += add;
+    in_block += add;
+
+    if (in_block > MD5_BLOCK_SIZE) {
+      process_block (md5_p, md5_p->md_buffer, in_block & ~BLOCK_SIZE_MASK);
+      /* the regions in the following copy operation will not overlap. */
+      memcpy (md5_p->md_buffer,
+	      md5_p->md_buffer + (in_block & ~BLOCK_SIZE_MASK),
+	      in_block & BLOCK_SIZE_MASK);
+      md5_p->md_buf_len = in_block & BLOCK_SIZE_MASK;
+    }
+
+    buffer = (const char *)buffer + add;
+    len -= add;
+  }
+
+  /* process available complete blocks right from the user buffer */
+  if (len > MD5_BLOCK_SIZE) {
+    process_block (md5_p, buffer, len & ~BLOCK_SIZE_MASK);
+    buffer = (const char *) buffer + (len & ~BLOCK_SIZE_MASK);
+    len &= BLOCK_SIZE_MASK;
+  }
+
+  /* copy remaining bytes into the internal buffer */
+  if (len > 0) {
+    memcpy (md5_p->md_buffer, buffer, len);
+    md5_p->md_buf_len = len;
+  }
+}
+
+/*
+ * md5_finish
+ *
+ * DESCRIPTION:
+ *
+ * Finish a progressing MD5 calculation and copy the resulting MD5
+ * signature into the result buffer which should be 16 bytes
+ * (MD5_SIZE).  After this call, the MD5 structure is invalid.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * md5_p - Pointer to MD5 structure which we are finishing.
+ *
+ * signature - A 16 byte buffer that will contain the MD5 signature.
+ */
+void	md5_finish(md5_t *md5_p, void *signature)
+{
+  md5_uint32	bytes, hold;
+  int		pad;
+
+  /* take yet unprocessed bytes into account */
+  bytes = md5_p->md_buf_len;
+
+  /*
+   * Count remaining bytes.  Modified to do this to better avoid
+   * overflows in the lower word -- Gray 10/97.
+   */
+  if (md5_p->md_total[0] > MAX_MD5_UINT32 - bytes) {
+    md5_p->md_total[1]++;
+    md5_p->md_total[0] -= (MAX_MD5_UINT32 - bytes);
+  }
+  else {
+    md5_p->md_total[0] += bytes;
+  }
+
+  /*
+   * Pad the buffer to the next MD5_BLOCK-byte boundary.  (RFC 1321,
+   * 3.1: Step 1).  We need enough room for two size words and the
+   * bytes left in the buffer.  For some reason even if we are equal
+   * to the block-size, we add an addition block of pad bytes.
+   */
+  pad = MD5_BLOCK_SIZE - (sizeof(md5_uint32) * 2) - bytes;
+  if (pad <= 0) {
+    pad += MD5_BLOCK_SIZE;
+  }
+
+  /*
+   * Modified from a fixed array to this assignment and memset to be
+   * more flexible with block-sizes -- Gray 10/97.
+   */
+  if (pad > 0) {
+    /* some sort of padding start byte */
+    md5_p->md_buffer[bytes] = (unsigned char)0x80;
+    if (pad > 1) {
+      memset (md5_p->md_buffer + bytes + 1, 0, pad - 1);
+    }
+    bytes += pad;
+  }
+
+  /* put the 64-bit file length in _bits_ (i.e. *8) at the end of the buffer */
+  hold = SWAP(md5_p->md_total[0] << 3);
+  memcpy(md5_p->md_buffer + bytes, &hold, sizeof(md5_uint32));
+  bytes += sizeof(md5_uint32);
+
+  /* shift the high word over by 3 and add in the top 3 bits from the low */
+  hold = SWAP((md5_p->md_total[1] << 3) | (md5_p->md_total[0] >> 29));
+  memcpy(md5_p->md_buffer + bytes, &hold, sizeof(md5_uint32));
+  bytes += sizeof(md5_uint32);
+
+  /* process last bytes, the padding chars, and size words */
+  process_block(md5_p, md5_p->md_buffer, bytes);
+  md5_get_result(md5_p, signature);
+}
+
+/*
+ * md5_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to calculate a MD5 signature for a buffer of
+ * bytes.  If you only have part of a buffer that you want to process
+ * then md5_init, md5_process, and md5_finish should be used.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * buffer - A buffer of bytes whose MD5 signature we are calculating.
+ *
+ * buf_len - The length of the buffer.
+ *
+ * signature - A 16 byte buffer that will contain the MD5 signature.
+ */
+void	md5_buffer(const char *buffer, const unsigned int buf_len,
+		   void *signature)
+{
+  md5_t		md5;
+
+  /* initialize the computation context */
+  md5_init(&md5);
+
+  /* process whole buffer but last buf_len % MD5_BLOCK bytes */
+  md5_process(&md5, buffer, buf_len);
+
+  /* put result in desired memory area */
+  md5_finish(&md5, signature);
+}
+
+/*
+ * md5_sig_to_string
+ *
+ * DESCRIPTION:
+ *
+ * Convert a MD5 signature in a 16 byte buffer into a hexadecimal string
+ * representation.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * signature - a 16 byte buffer that contains the MD5 signature.
+ *
+ * str - a string of charactes which should be at least 33 bytes long (2
+ * characters per MD5 byte and 1 for the \0).
+ *
+ * str_len - the length of the string.
+ */
+void	md5_sig_to_string(void *signature, char *str, const int str_len)
+{
+  unsigned char	*sig_p;
+  char		*str_p, *max_p;
+  unsigned int	high, low;
+  
+  str_p = str;
+  max_p = str + str_len;
+  
+  for (sig_p = (unsigned char *)signature;
+       sig_p < (unsigned char *)signature + MD5_SIZE;
+       sig_p++) {
+    high = *sig_p / 16;
+    low = *sig_p % 16;
+    /* account for 2 chars */
+    if (str_p + 1 >= max_p) {
+      break;
+    }
+    *str_p++ = HEX_STRING[high];
+    *str_p++ = HEX_STRING[low];
+  }
+  /* account for 2 chars */
+  if (str_p < max_p) {
+    *str_p++ = '\0';
+  }
+}
+
+/*
+ * md5_sig_from_string
+ *
+ * DESCRIPTION:
+ *
+ * Convert a MD5 signature from a hexadecimal string representation into
+ * a 16 byte buffer.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * signature - A 16 byte buffer that will contain the MD5 signature.
+ *
+ * str - A string of charactes which _must_ be at least 32 bytes long (2
+ * characters per MD5 byte).
+ */
+void	md5_sig_from_string(void *signature, const char *str)
+{
+  unsigned char	*sig_p;
+  const char	*str_p;
+  char		*hex;
+  unsigned int	high, low, val;
+  
+  hex = HEX_STRING;
+  sig_p = signature;
+  
+  for (str_p = str; str_p < str + MD5_SIZE * 2; str_p += 2) {
+    high = strchr(hex, *str_p) - hex;
+    low = strchr(hex, *(str_p + 1)) - hex;
+    val = high * 16 + low;
+    *sig_p++ = val;
+  }
+}
diff --git a/libmd5/md5.h b/libmd5/md5.h
new file mode 100644
index 0000000..6b35fc6
--- /dev/null
+++ b/libmd5/md5.h
@@ -0,0 +1,225 @@
+/*
+ * Declaration of functions and data types used for MD5 sum computing
+ * library functions.  Copyright (C) 1995, 1996 Free Software
+ * Foundation, Inc.  NOTE: The canonical source of this file is
+ * maintained with the GNU C Library.  Bugs can be reported to
+ * bug-glibc@prep.ai.mit.edu.
+ *
+ * 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, 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.
+ *
+ * $Id$
+ */
+
+/*
+ * NOTE: during quick performance tests on a sun ultra and an alpha
+ * 255 300, the md5 libraries performed upwards of 3mb/sec.  That
+ * included disk i/o on bobcat and panther.
+ */
+
+#ifndef __MD5_H__
+#define __MD5_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Size of a standard MD5 signature in bytes.  This definition is for
+ * external programs only.  The MD5 routines themselves reference the
+ * signature as 4 unsigned 32-bit integers.
+ */
+#define MD5_SIZE	16
+
+/*
+ * NOTE: the following is assumed to generate a 32-bit unsigned data
+ * type.
+ */
+typedef unsigned int		md5_uint32;
+#define MAX_MD5_UINT32		((md5_uint32)4294967295U)
+
+/*
+ * The MD5 algorithm works on blocks of characters of 64 bytes.  This
+ * is an internal value only and is not necessary for external use.
+ */
+#define MD5_BLOCK_SIZE		64
+
+/*
+ * Structure to save state of computation between the single steps.
+ */
+typedef struct
+{
+  md5_uint32	md_A;			/* accumulater 1 */
+  md5_uint32	md_B;			/* accumulater 2 */
+  md5_uint32	md_C;			/* accumulater 3 */
+  md5_uint32	md_D;			/* accumulater 4 */
+
+  md5_uint32	md_total[2];		/* totaling storage */
+  md5_uint32	md_buf_len;		/* length of the storage buffer */
+  char		md_buffer[MD5_BLOCK_SIZE * 2];	/* character storage buffer */
+} md5_t;
+
+/*<<<<<<<<<<  The below prototypes are auto-generated by fillproto */
+
+/*
+ * md5_init
+ *
+ * DESCRIPTION:
+ *
+ * Initialize structure containing state of MD5 computation. (RFC 1321,
+ * 3.3: Step 3).  This is for progressive MD5 calculations only.  If
+ * you have the complete string available, md5_buffer should be used.
+ * md5_process should be called for each bunch of bytes and after the
+ * last process call, md5_finish should be called to get the
+ * signature.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * md5_p - Pointer to md5 structure that we are initializing.
+ */
+extern
+void	md5_init(md5_t *md5_p);
+
+/*
+ * md5_process
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to progressively calculate a MD5 signature some
+ * number of bytes at a time.  If you have the complete string
+ * available, md5_buffer should be used.  The MD5 structure should
+ * have been initialized with md5_init and after the last process
+ * call, md5_finish should be called to get the results.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * md5_p - Pointer to MD5 structure which we are progressively updating.
+ *
+ * buffer - A buffer of bytes whose MD5 signature we are calculating.
+ *
+ * buf_len - The length of the buffer.
+ */
+extern
+void	md5_process(md5_t *md5_p, const void *buffer,
+		    const unsigned int buf_len);
+
+/*
+ * md5_finish
+ *
+ * DESCRIPTION:
+ *
+ * Finish a progressing MD5 calculation and copy the resulting MD5
+ * signature into the result buffer which should be 16 bytes
+ * (MD5_SIZE).  After this call, the MD5 structure is invalid.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * md5_p - Pointer to MD5 structure which we are finishing.
+ *
+ * signature - A 16 byte buffer that will contain the MD5 signature.
+ */
+extern
+void	md5_finish(md5_t *md5_p, void *signature);
+
+/*
+ * md5_buffer
+ *
+ * DESCRIPTION:
+ *
+ * This function is used to calculate a MD5 signature for a buffer of
+ * bytes.  If you only have part of a buffer that you want to process
+ * then md5_init, md5_process, and md5_finish should be used.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * buffer - A buffer of bytes whose MD5 signature we are calculating.
+ *
+ * buf_len - The length of the buffer.
+ *
+ * signature - A 16 byte buffer that will contain the MD5 signature.
+ */
+extern
+void	md5_buffer(const char *buffer, const unsigned int buf_len,
+		   void *signature);
+
+/*
+ * md5_sig_to_string
+ *
+ * DESCRIPTION:
+ *
+ * Convert a MD5 signature in a 16 byte buffer into a hexadecimal string
+ * representation.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * signature - a 16 byte buffer that contains the MD5 signature.
+ *
+ * str - a string of charactes which should be at least 33 bytes long (2
+ * characters per MD5 byte and 1 for the \0).
+ *
+ * str_len - the length of the string.
+ */
+extern
+void	md5_sig_to_string(void *signature, char *str, const int str_len);
+
+/*
+ * md5_sig_from_string
+ *
+ * DESCRIPTION:
+ *
+ * Convert a MD5 signature from a hexadecimal string representation into
+ * a 16 byte buffer.
+ *
+ * RETURNS:
+ *
+ * None.
+ *
+ * ARGUMENTS:
+ *
+ * signature - A 16 byte buffer that will contain the MD5 signature.
+ *
+ * str - A string of charactes which _must_ be at least 32 bytes long (2
+ * characters per MD5 byte).
+ */
+extern
+void	md5_sig_from_string(void *signature, const char *str);
+
+/*<<<<<<<<<<   This is end of the auto-generated output from fillproto. */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! __MD5_H__ */
diff --git a/libmd5/md5_loc.h b/libmd5/md5_loc.h
new file mode 100644
index 0000000..03aeebf
--- /dev/null
+++ b/libmd5/md5_loc.h
@@ -0,0 +1,106 @@
+/*
+ * Local defines for the md5 functions.
+ *
+ * $Id$
+ */
+
+/*
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it is
+ * identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided that
+ * such works are identified as "derived from the RSA Data Security,
+ * Inc. MD5 Message-Digest Algorithm" in all material mentioning or
+ * referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either the
+ * merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is" without
+ * express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#ifndef __MD5_LOC_H__
+#define __MD5_LOC_H__
+
+#define HEX_STRING	"0123456789abcdef"	/* to convert to hex */
+#define BLOCK_SIZE_MASK	(MD5_BLOCK_SIZE - 1)
+
+/*
+ * Define my endian-ness.  Could not do in a portable manner using the
+ * include files -- grumble.
+ */
+#if defined(__alpha) || defined(WIN32) || defined(__i386__)
+/*
+ * little endian
+ */
+#define SWAP(n)	(n)
+#endif
+
+#ifdef __sparc
+/*
+ * big endian - big is better
+ */
+#define SWAP(n)	\
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#endif
+
+/*
+ * These are the four functions used in the four steps of the MD5
+ * algorithm and defined in the RFC 1321.  The first function is a
+ * little bit optimized (as found in Colin Plumbs public domain
+ * implementation).
+ */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d)	(d ^ (b & (c ^ d)))
+#define FG(b, c, d)	FF(d, b, c)
+#define FH(b, c, d)	(b ^ c ^ d)
+#define FI(b, c, d)	(c ^ (b | ~d))
+
+/*
+ * It is unfortunate that C does not provide an operator for cyclic
+ * rotation.  Hope the C compiler is smart enough.  -- Modified to
+ * remove the w = at the front - Gray 2/97
+ */
+#define CYCLIC(w, s)	((w << s) | (w >> (32 - s)))
+
+/*
+ * First Round: using the given function, the context and a constant
+ * the next context is computed.  Because the algorithms processing
+ * unit is a 32-bit word and it is determined to work on words in
+ * little endian byte order we perhaps have to change the byte order
+ * before the computation.  To reduce the work for the next steps we
+ * store the swapped words in the array CORRECT_WORDS. -- Modified to
+ * fix the handling of unaligned buffer spaces - Gray 7/97
+ */
+#define OP1(a, b, c, d, b_p, c_p, s, T)				\
+     do {							\
+       memcpy(c_p, b_p, sizeof(md5_uint32));       		\
+       *c_p = SWAP(*c_p);					\
+       a += FF (b, c, d) + *c_p + T;				\
+       a = CYCLIC (a, s);					\
+       a += b;							\
+       b_p = (char *)b_p + sizeof(md5_uint32);			\
+       c_p++;							\
+    } while (0)
+
+/*
+ * Second to Fourth Round: we have the possibly swapped words in
+ * CORRECT_WORDS.  Redefine the macro to take an additional first
+ * argument specifying the function to use.
+ */
+#define OP234(FUNC, a, b, c, d, k, s, T)		\
+    do { 						\
+      a += FUNC (b, c, d) + k + T;			\
+      a = CYCLIC (a, s);				\
+      a += b;						\
+    } while (0)
+
+#endif /* ! __MD5_LOC_H__ */
diff --git a/packages/rpm/doxygen.spec b/packages/rpm/doxygen.spec
index 04569f7..ce08c50 100644
--- a/packages/rpm/doxygen.spec
+++ b/packages/rpm/doxygen.spec
@@ -1,6 +1,6 @@
 Summary: A documentation system for C/C++.
 Name: doxygen
-Version: 1.3.4_20031019
+Version: 1.3.4_20031026
 Release: 1
 Epoch: 1
 Source0: ftp://ftp.stack.nl/pub/users/dimitri/%{name}-%{version}.src.tar.gz
diff --git a/src/dot.cpp b/src/dot.cpp
index 79c1320..1b506b1 100644
--- a/src/dot.cpp
+++ b/src/dot.cpp
@@ -31,6 +31,7 @@
 #include <qdir.h>
 #include <qfile.h>
 #include <qtextstream.h>
+#include <md5.h>
 
 //--------------------------------------------------------------------
 
@@ -1382,7 +1383,86 @@ void writeDotGraph(DotNode *root,
   }
 }
 
-static void findMaximalDotGraph(DotNode *root,
+/*! Computes a 16 byte md5 checksum for a given dot graph.
+ *  The md5 checksum is returned as a 32 character ASCII string.
+ */
+QCString computeMd5Signature(DotNode *root,
+                   DotNode::GraphType gt,
+                   GraphOutputFormat format,
+                   bool lrRank,
+                   bool renderParents,
+                   int distance,
+                   bool backArrows
+                  )
+{
+  //printf("computeMd5Signature\n");
+  QString buf;
+  QTextStream md5stream(&buf,IO_WriteOnly);
+  if (lrRank)
+  {
+    md5stream << "rankdir=LR;" << endl;
+  }
+  root->clearWriteFlag();
+  root->write(md5stream,gt,format,gt!=DotNode::CallGraph,TRUE,distance,backArrows);
+  if (renderParents && root->m_parents) 
+  {
+    QListIterator<DotNode>  dnli(*root->m_parents);
+    DotNode *pn;
+    for (dnli.toFirst();(pn=dnli.current());++dnli)
+    {
+      if (pn->m_distance<=distance) 
+      {
+        root->writeArrow(md5stream,
+            gt,
+            format,
+            pn,
+            pn->m_edgeInfo->at(pn->m_children->findRef(root)),
+            FALSE,
+            backArrows
+            );
+      }
+      pn->write(md5stream,gt,format,TRUE,FALSE,distance,backArrows);
+    }
+  }
+  char md5_sig[16];
+  QCString sigStr(33);
+  md5_buffer(buf.ascii(),buf.length(),md5_sig);
+  md5_sig_to_string(md5_sig,sigStr.data(),33);
+  //printf("md5: %s | file: %s\n",sigStr,baseName.data());
+  return sigStr;
+}
+
+/*! Checks if a file "baseName".md5 exists. If so the contents
+ *  are compared with \a md5. If equal FALSE is returned. If the .md5
+ *  file does not exist or its contents are not equal to \a md5, 
+ *  a new .md5 is generated with the \a md5 string as contents.
+ */
+static bool checkAndUpdateMd5Signature(const QCString &baseName,const QCString &md5)
+{
+  QFile f(baseName+".md5");
+  if (f.open(IO_ReadOnly))
+  {
+    // read checksum
+    QCString md5stored(33);
+    int bytesRead=f.readBlock(md5stored.data(),32);
+    // compare checksum
+    if (bytesRead==32 && md5==md5stored)
+    {
+      // bail out if equal
+      return FALSE;
+    }
+  }
+  f.close();
+  // create checksum file
+  if (f.open(IO_WriteOnly))
+  {
+    f.writeBlock(md5.data(),32); 
+    f.close();
+  }
+  return TRUE;
+}
+
+static bool findMaximalDotGraph(DotNode *root,
                                 int maxDist,
                                 const QCString &baseName,
                                 QDir &thisDir,
@@ -1402,6 +1482,10 @@ static void findMaximalDotGraph(DotNode *root,
   int maxDotGraphHeight = Config_getInt("MAX_DOT_GRAPH_HEIGHT");
   int lastFit=minDistance;
 
+  QCString md5 = computeMd5Signature(root,gt,format,lrRank,
+                              renderParents,maxDistance,backArrows);
+  if (!checkAndUpdateMd5Signature(baseName,md5)) return FALSE;
+
   // binary search for the maximal inheritance depth that fits in a reasonable
   // sized image (dimensions: Config_getInt("MAX_DOT_GRAPH_WIDTH"), Config_getInt("MAX_DOT_GRAPH_HEIGHT"))
   while (minDistance<=maxDistance)
@@ -1417,7 +1501,7 @@ static void findMaximalDotGraph(DotNode *root,
     if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
     {
       err("Problems running dot. Check your installation!\n");
-      return;
+      return FALSE;
     }
 
     // extract bounding box from the result
@@ -1461,6 +1545,7 @@ static void findMaximalDotGraph(DotNode *root,
                 lastFit,
                 backArrows
                );
+  return TRUE;
 }
 
 QCString DotClassGraph::diskName() const
@@ -1520,105 +1605,108 @@ QCString DotClassGraph::writeGraph(QTextStream &out,
   }
   baseName = convertNameToFile(diskName());
 
-  findMaximalDotGraph(m_startNode,QMIN(m_recDepth,m_maxDistance),baseName,
-                      thisDir,m_graphType,format,!isTBRank,m_graphType==DotNode::Inheritance);
 
-  if (format==BITMAP) // run dot to create a bitmap image
+  if (findMaximalDotGraph(m_startNode,QMIN(m_recDepth,m_maxDistance),baseName,
+        thisDir,m_graphType,format,!isTBRank,m_graphType==DotNode::Inheritance))
   {
-    QCString dotArgs(maxCmdLine);
-    QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
-    QCString imgName = baseName+"."+imgExt;
-    dotArgs.sprintf("-T%s \"%s.dot\" -o \"%s\"",
-                   imgExt.data(),baseName.data(),imgName.data());
-    if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
-    {
-       err("Error: Problems running dot. Check your installation!\n");
-       QDir::setCurrent(oldDir);
-       return baseName;
-    }
-    checkDotResult(imgName);
-    if (generateImageMap)
+
+    if (format==BITMAP) // run dot to create a bitmap image
     {
-      // run dot again to create an image map
-      dotArgs.sprintf("-Timap \"%s.dot\" -o \"%s.map\"",baseName.data(),baseName.data());
+      QCString dotArgs(maxCmdLine);
+      QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+      QCString imgName = baseName+"."+imgExt;
+      dotArgs.sprintf("-T%s \"%s.dot\" -o \"%s\"",
+          imgExt.data(),baseName.data(),imgName.data());
       if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
       {
         err("Error: Problems running dot. Check your installation!\n");
         QDir::setCurrent(oldDir);
         return baseName;
       }
-      QCString mapLabel = convertNameToFile(m_startNode->m_label+"_"+mapName);
-      out << "<p><center><img src=\"" << baseName << "." 
+      checkDotResult(imgName);
+      if (generateImageMap)
+      {
+        // run dot again to create an image map
+        dotArgs.sprintf("-Timap \"%s.dot\" -o \"%s.map\"",baseName.data(),baseName.data());
+        if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
+        {
+          err("Error: Problems running dot. Check your installation!\n");
+          QDir::setCurrent(oldDir);
+          return baseName;
+        }
+        QCString mapLabel = convertNameToFile(m_startNode->m_label+"_"+mapName);
+        out << "<p><center><img src=\"" << baseName << "." 
           << imgExt << "\" border=\"0\" usemap=\"#"
           << mapLabel << "\" alt=\"";
-      switch (m_graphType)
+        switch (m_graphType)
+        {
+          case DotNode::Collaboration:
+            out << "Collaboration graph";
+            break;
+            //case Interface:
+            //  out << "Interface dependency graph";
+            //  break;
+          case DotNode::Inheritance:
+            out << "Inheritance graph";
+            break;
+          default:
+            ASSERT(0);
+            break;
+        }
+        out << "\"></center>" << endl;
+        QString tmpstr;
+        QTextOStream tmpout(&tmpstr);
+        convertMapFile(tmpout,baseName+".map");
+        if (!tmpstr.isEmpty())
+        {
+          out << "<map name=\"" << mapLabel << "\">" << endl;
+          out << tmpstr;
+          out << "</map>" << endl;
+        }
+        thisDir.remove(baseName+".map");
+      }
+    }
+    else if (format==EPS) // run dot to create a .eps image
+    {
+      QCString dotArgs(maxCmdLine);
+      dotArgs.sprintf("-Tps \"%s.dot\" -o \"%s.eps\"",baseName.data(),baseName.data());
+      if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
       {
-        case DotNode::Collaboration:
-          out << "Collaboration graph";
-          break;
-        //case Interface:
-        //  out << "Interface dependency graph";
-        //  break;
-        case DotNode::Inheritance:
-          out << "Inheritance graph";
-          break;
-        default:
-          ASSERT(0);
-          break;
+        err("Error: Problems running dot. Check your installation!\n");
+        QDir::setCurrent(oldDir);
+        return baseName;
       }
-      out << "\"></center>" << endl;
-      QString tmpstr;
-      QTextOStream tmpout(&tmpstr);
-      convertMapFile(tmpout,baseName+".map");
-      if (!tmpstr.isEmpty())
+      int width,height;
+      if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
       {
-        out << "<map name=\"" << mapLabel << "\">" << endl;
-        out << tmpstr;
-        out << "</map>" << endl;
+        err("Error: Could not extract bounding box from .eps!\n");
+        QDir::setCurrent(oldDir);
+        return baseName;
       }
-      thisDir.remove(baseName+".map");
-    }
-  }
-  else if (format==EPS) // run dot to create a .eps image
-  {
-    QCString dotArgs(maxCmdLine);
-    dotArgs.sprintf("-Tps \"%s.dot\" -o \"%s.eps\"",baseName.data(),baseName.data());
-    if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
-    {
-       err("Error: Problems running dot. Check your installation!\n");
-       QDir::setCurrent(oldDir);
-       return baseName;
-    }
-    int width,height;
-    if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
-    {
-      err("Error: Could not extract bounding box from .eps!\n");
-      QDir::setCurrent(oldDir);
-      return baseName;
-    }
-    if (Config_getBool("USE_PDFLATEX"))
-    {
-      QCString epstopdfArgs(maxCmdLine);
-      epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
-                     baseName.data(),baseName.data());
-      if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
+      if (Config_getBool("USE_PDFLATEX"))
       {
-         err("Error: Problems running epstopdf. Check your TeX installation!\n");
-         QDir::setCurrent(oldDir);
-         return baseName;
+        QCString epstopdfArgs(maxCmdLine);
+        epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
+            baseName.data(),baseName.data());
+        if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
+        {
+          err("Error: Problems running epstopdf. Check your TeX installation!\n");
+          QDir::setCurrent(oldDir);
+          return baseName;
+        }
       }
+      int maxWidth = 420; /* approx. page width in points */
+
+      out << "\\begin{figure}[H]\n"
+        "\\begin{center}\n"
+        "\\leavevmode\n"
+        "\\includegraphics[width=" << QMIN(width/2,maxWidth) 
+        << "pt]{" << baseName << "}\n"
+        "\\end{center}\n"
+        "\\end{figure}\n";
     }
-    int maxWidth = 420; /* approx. page width in points */
-   
-    out << "\\begin{figure}[H]\n"
-           "\\begin{center}\n"
-           "\\leavevmode\n"
-           "\\includegraphics[width=" << QMIN(width/2,maxWidth) 
-                                      << "pt]{" << baseName << "}\n"
-           "\\end{center}\n"
-           "\\end{figure}\n";
+    if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
   }
-  if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
 
   QDir::setCurrent(oldDir);
   return baseName;
@@ -1763,101 +1851,103 @@ QCString DotInclDepGraph::writeGraph(QTextStream &out,
   QCString mapName=m_startNode->m_label.copy();
   if (m_inverse) mapName+="dep";
 
-  findMaximalDotGraph(m_startNode,QMIN(m_recDepth,m_maxDistance),
+  if (findMaximalDotGraph(m_startNode,QMIN(m_recDepth,m_maxDistance),
                       baseName,thisDir,DotNode::Dependency,format,
-                      FALSE,FALSE,!m_inverse);
-
-  if (format==BITMAP)
+                      FALSE,FALSE,!m_inverse)
+     )
   {
-    // run dot to create a bitmap image
-    QCString dotArgs(maxCmdLine);
-    QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
-    QCString imgName=baseName+"."+imgExt;
-    dotArgs.sprintf("-T%s \"%s.dot\" -o \"%s\"",
-                   imgExt.data(),baseName.data(),imgName.data());
-    if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
-    {
-      err("Problems running dot. Check your installation!\n");
-      QDir::setCurrent(oldDir);
-      return baseName;
-    }
-    checkDotResult(imgName);
-
-    if (generateImageMap)
+    if (format==BITMAP)
     {
-      // run dot again to create an image map
-      dotArgs.sprintf("-Timap \"%s.dot\" -o \"%s.map\"",
-                      baseName.data(),baseName.data());
+      // run dot to create a bitmap image
+      QCString dotArgs(maxCmdLine);
+      QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");
+      QCString imgName=baseName+"."+imgExt;
+      dotArgs.sprintf("-T%s \"%s.dot\" -o \"%s\"",
+          imgExt.data(),baseName.data(),imgName.data());
       if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
       {
         err("Problems running dot. Check your installation!\n");
         QDir::setCurrent(oldDir);
         return baseName;
       }
+      checkDotResult(imgName);
 
-      out << "<p><center><img src=\"" << baseName << "." 
+      if (generateImageMap)
+      {
+        // run dot again to create an image map
+        dotArgs.sprintf("-Timap \"%s.dot\" -o \"%s.map\"",
+            baseName.data(),baseName.data());
+        if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
+        {
+          err("Problems running dot. Check your installation!\n");
+          QDir::setCurrent(oldDir);
+          return baseName;
+        }
+
+        out << "<p><center><img src=\"" << baseName << "." 
           << imgExt << "\" border=\"0\" usemap=\"#"
           << mapName << "_map\" alt=\"";
-      if (m_inverse) out << "Included by dependency graph"; else out << "Include dependency graph";
-      out << "\">";
-      out << "</center>" << endl;
-      QString tmpstr;
-      QTextOStream tmpout(&tmpstr);
-      convertMapFile(tmpout,baseName+".map");
-      if (!tmpstr.isEmpty())
-      {
-        out << "<map name=\"" << mapName << "_map\">" << endl;
-        out << tmpstr;
-        out << "</map>" << endl;
+        if (m_inverse) out << "Included by dependency graph"; else out << "Include dependency graph";
+        out << "\">";
+        out << "</center>" << endl;
+        QString tmpstr;
+        QTextOStream tmpout(&tmpstr);
+        convertMapFile(tmpout,baseName+".map");
+        if (!tmpstr.isEmpty())
+        {
+          out << "<map name=\"" << mapName << "_map\">" << endl;
+          out << tmpstr;
+          out << "</map>" << endl;
+        }
+        thisDir.remove(baseName+".map");
       }
-      thisDir.remove(baseName+".map");
     }
-  }
-  else if (format==EPS)
-  {
-    // run dot to create a .eps image
-    QCString dotArgs(maxCmdLine);
-    dotArgs.sprintf("-Tps \"%s.dot\" -o \"%s.eps\"",
-                   baseName.data(),baseName.data());
-    if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
+    else if (format==EPS)
     {
-      err("Problems running dot. Check your installation!\n");
-      QDir::setCurrent(oldDir);
-      return baseName;
-    }
-    int width,height;
-    if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
-    {
-      err("Error: Could not extract bounding box from .eps!\n");
-      QDir::setCurrent(oldDir);
-      return baseName;
-    }
-    if (Config_getBool("USE_PDFLATEX"))
-    {
-      QCString epstopdfArgs(maxCmdLine);
-      epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
-                     baseName.data(),baseName.data());
-      if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
+      // run dot to create a .eps image
+      QCString dotArgs(maxCmdLine);
+      dotArgs.sprintf("-Tps \"%s.dot\" -o \"%s.eps\"",
+          baseName.data(),baseName.data());
+      if (iSystem(Config_getString("DOT_PATH")+"dot",dotArgs)!=0)
       {
-         err("Error: Problems running epstopdf. Check your TeX installation!\n");
-         QDir::setCurrent(oldDir);
-         return baseName;
+        err("Problems running dot. Check your installation!\n");
+        QDir::setCurrent(oldDir);
+        return baseName;
+      }
+      int width,height;
+      if (!readBoundingBoxEPS(baseName+".eps",&width,&height))
+      {
+        err("Error: Could not extract bounding box from .eps!\n");
+        QDir::setCurrent(oldDir);
+        return baseName;
+      }
+      if (Config_getBool("USE_PDFLATEX"))
+      {
+        QCString epstopdfArgs(maxCmdLine);
+        epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"",
+            baseName.data(),baseName.data());
+        if (iSystem("epstopdf",epstopdfArgs,TRUE)!=0)
+        {
+          err("Error: Problems running epstopdf. Check your TeX installation!\n");
+          QDir::setCurrent(oldDir);
+          return baseName;
+        }
       }
+      int maxWidth = 420; /* approx. page width in points */
+
+      out << "\\begin{figure}[H]\n"
+        "\\begin{center}\n"
+        "\\leavevmode\n"
+        //"\\setlength{\\epsfxsize}{" << QMIN(width/2,maxWidth) << "pt}\n"
+        //"\\epsfbox{" << baseName << ".eps}\n"
+        "\\includegraphics[width=" << QMIN(width/2,maxWidth) 
+        << "pt]{" << baseName << "}\n"
+        "\\end{center}\n"
+        "\\end{figure}\n";
     }
-    int maxWidth = 420; /* approx. page width in points */
-   
-    out << "\\begin{figure}[H]\n"
-           "\\begin{center}\n"
-           "\\leavevmode\n"
-           //"\\setlength{\\epsfxsize}{" << QMIN(width/2,maxWidth) << "pt}\n"
-           //"\\epsfbox{" << baseName << ".eps}\n"
-           "\\includegraphics[width=" << QMIN(width/2,maxWidth) 
-                                      << "pt]{" << baseName << "}\n"
-           "\\end{center}\n"
-           "\\end{figure}\n";
-  }
 
-  if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
+    if (Config_getBool("DOT_CLEANUP")) thisDir.remove(baseName+".dot");
+  }
 
   QDir::setCurrent(oldDir);
   return baseName;
diff --git a/src/dot.h b/src/dot.h
index 1723e36..6f89200 100644
--- a/src/dot.h
+++ b/src/dot.h
@@ -99,14 +99,16 @@ class DotNode
     friend class DotNodeList;
     friend class DotCallGraph;
     friend void writeDotGraph(
-                      DotNode *root,
-                      GraphType gt,
-                      GraphOutputFormat f,
-                      const QCString &baseName,
-                      bool lrRank,
-                      bool renderParents,
-                      int distance,
-                      bool backArrow
+                      DotNode *root, GraphType gt,
+                      GraphOutputFormat f, const QCString &baseName,
+                      bool lrRank, bool renderParents,
+                      int distance, bool backArrows
+                     );
+    friend QCString computeMd5Signature(
+                      DotNode *root, GraphType gt,
+                      GraphOutputFormat f, 
+                      bool lrRank, bool renderParents,
+                      int distance, bool backArrows
                      );
 };
 
diff --git a/src/doxygen.pro.in b/src/doxygen.pro.in
index d397106..8469a12 100644
--- a/src/doxygen.pro.in
+++ b/src/doxygen.pro.in
@@ -18,18 +18,18 @@ TEMPLATE     =	app.t
 CONFIG       =	console warn_on $extraopts
 HEADERS      =	doxygen.h 
 SOURCES      =	main.cpp 
-unix:LIBS                  += -L../lib -ldoxygen -ldoxycfg -lqtools -lpng
+unix:LIBS                  += -L../lib -ldoxygen -ldoxycfg -lqtools -lpng -lmd5
 win32:INCLUDEPATH          += .
-win32-mingw:LIBS           += -L../lib -ldoxygen -ldoxycfg -lqtools -lpng
-win32-msvc:LIBS            += qtools.lib png.lib doxygen.lib doxycfg.lib shell32.lib 
+win32-mingw:LIBS           += -L../lib -ldoxygen -ldoxycfg -lqtools -lpng -lmd5
+win32-msvc:LIBS            += qtools.lib png.lib md5.lib doxygen.lib doxycfg.lib shell32.lib 
 win32-msvc:TMAKE_LFLAGS    += /LIBPATH:..\lib
-win32-borland:LIBS         += qtools.lib png.lib doxygen.lib doxycfg.lib shell32.lib 
+win32-borland:LIBS         += qtools.lib png.lib md5.lib doxygen.lib doxycfg.lib shell32.lib 
 win32-borland:TMAKE_LFLAGS += -L..\lib -L$(BCB)\lib\psdk
 win32:TMAKE_CXXFLAGS       += -DQT_NODLL
-win32-g++:LIBS             = -L../lib -ldoxygen -ldoxycfg -lqtools -lpng
+win32-g++:LIBS             = -L../lib -ldoxygen -ldoxycfg -lqtools -lpng -lmd5
 win32-g++:TMAKE_CXXFLAGS   += -fno-exceptions -fno-rtti
-INCLUDEPATH                += ../qtools ../libpng .
-win32-g++:INCLUDEPATH      -= ../libpng
+INCLUDEPATH                += ../qtools ../libpng ../libmd5 .
+#win32-g++:INCLUDEPATH      -= ../libpng
 DESTDIR                    =  ../bin
 TARGET                     =  doxygen
 unix:TARGETDEPS            =  ../lib/libdoxygen.a ../lib/libdoxycfg.a
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
index 99bb708..3a260a2 100644
--- a/src/htmlgen.cpp
+++ b/src/htmlgen.cpp
@@ -1412,7 +1412,7 @@ void HtmlGenerator::writeSearchPage()
         writeDefaultQuickLinks(t,TRUE,HLI_Search);
       }
 
-      t << "<?php \n\n";
+      t << "\n<?php\n\n";
       t << "function search_results()\n";
       t << "{\n";
       t << "  return \"" << theTranslator->trSearchResultsTitle() << "\";\n";
diff --git a/src/index.cpp b/src/index.cpp
index 766bd80..831512b 100644
--- a/src/index.cpp
+++ b/src/index.cpp
@@ -1011,11 +1011,11 @@ void writeFileIndex(OutputList &ol)
           ol.endBold();
           if (hasHtmlHelp)
           {
-            htmlHelp->addContentsItem(FALSE,fd->name(),0);
+            htmlHelp->addContentsItem(FALSE,fullName,0);
           }
           if (hasFtvHelp)
           {
-            ftvHelp->addContentsItem(FALSE,0,0,0,fd->name());
+            ftvHelp->addContentsItem(FALSE,0,0,0,fullName);
           }
         }
         if (src)
diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp
index 1a6c889..f4ff312 100644
--- a/src/latexdocvisitor.cpp
+++ b/src/latexdocvisitor.cpp
@@ -249,12 +249,12 @@ void LatexDocVisitor::visit(DocVerbatim *s)
     case DocVerbatim::Code: 
       m_t << "\n\n\\footnotesize\\begin{verbatim}"; 
       parseCode(m_ci,s->context(),s->text().latin1(),s->isExample(),s->exampleFile());
-      m_t << "\\end{verbatim}\\normalsize" << endl; 
+      m_t << "\\end{verbatim}\n\\normalsize" << endl; 
       break;
     case DocVerbatim::Verbatim: 
       m_t << "\n\n\\footnotesize\\begin{verbatim}"; 
       m_t << s->text();
-      m_t << "\\end{verbatim}\\normalsize" << endl; 
+      m_t << "\\end{verbatim}\n\\normalsize" << endl; 
       break;
     case DocVerbatim::HtmlOnly: 
     case DocVerbatim::XmlOnly: 
@@ -310,7 +310,7 @@ void LatexDocVisitor::visit(DocInclude *inc)
     case DocInclude::Include: 
       m_t << "\n\n\\footnotesize\\begin{verbatim}"; 
       parseCode(m_ci,inc->context(),inc->text().latin1(),inc->isExample(),inc->exampleFile());
-      m_t << "\\end{verbatim}\\normalsize" << endl; 
+      m_t << "\\end{verbatim}\n\\normalsize" << endl; 
       break;
     case DocInclude::DontInclude: 
       break;
@@ -319,7 +319,7 @@ void LatexDocVisitor::visit(DocInclude *inc)
     case DocInclude::VerbInclude: 
       m_t << "\n\n\\footnotesize\\begin{verbatim}"; 
       m_t << inc->text();
-      m_t << "\\end{verbatim}\\normalsize" << endl; 
+      m_t << "\\end{verbatim}\n\\normalsize" << endl; 
       break;
   }
 }
@@ -344,7 +344,7 @@ void LatexDocVisitor::visit(DocIncOperator *op)
   if (op->isLast())  
   {
     popEnabled();
-    if (!m_hide) m_t << "\\end{verbatim}\\normalsize" << endl; 
+    if (!m_hide) m_t << "\\end{verbatim}\n\\normalsize" << endl; 
   }
   else
   {
diff --git a/src/libdoxygen.pro.in b/src/libdoxygen.pro.in
index 630a39e..53b3341 100644
--- a/src/libdoxygen.pro.in
+++ b/src/libdoxygen.pro.in
@@ -186,6 +186,7 @@ win32-msvc:TMAKE_CXXFLAGS  += -Zm200
 win32-g++:TMAKE_CXXFLAGS   += -fno-exceptions -fno-rtti
 INCLUDEPATH                += ../qtools
 INCLUDEPATH                += ../libpng
+INCLUDEPATH                += ../libmd5
 win32:INCLUDEPATH          += .
 win32-g++:INCLUDEPATH      = ../qtools /usr/include/libpng12
 DESTDIR                    =  ../lib
diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp
index f7f8c84..648d3b7 100644
--- a/src/mandocvisitor.cpp
+++ b/src/mandocvisitor.cpp
@@ -436,6 +436,7 @@ void ManDocVisitor::visitPre(DocSimpleList *)
 {
   if (m_hide) return;
   m_indent+=2;
+  m_t << ".PD 0" << endl;
 }
 
 void ManDocVisitor::visitPost(DocSimpleList *)
@@ -482,6 +483,7 @@ void ManDocVisitor::visitPre(DocHtmlList *)
 {
   if (m_hide) return;
   m_indent+=2;
+  m_t << ".PD 0" << endl;
 }
 
 void ManDocVisitor::visitPost(DocHtmlList *) 
diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp
index 36521ca..4ef5e49 100644
--- a/src/rtfdocvisitor.cpp
+++ b/src/rtfdocvisitor.cpp
@@ -1221,8 +1221,9 @@ void RTFDocVisitor::writeDotFile(const QString &fileName)
   m_t << "{" << endl;
   m_t << rtf_Style_Reset << endl;
   m_t << "\\par\\pard \\qc {\\field\\flddirty {\\*\\fldinst INCLUDEPICTURE ";
-  m_t << outDir << "\\" << baseName;
+  m_t << baseName << "." << Config_getEnum("DOT_IMAGE_FORMAT");
   m_t << " \\\\d \\\\*MERGEFORMAT}{\\fldrslt IMAGE}}\\par" << endl;
   m_t << "}" << endl;
 }
 
+
diff --git a/src/scanner.l b/src/scanner.l
index ae63c72..d70ad39 100644
--- a/src/scanner.l
+++ b/src/scanner.l
@@ -159,6 +159,9 @@ static QCString         xrefItemTitle;
 static QCString         xrefListTitle;
 
 static QCString         g_skipBlockName;
+static QCString         oldStyleArgType;
+static QCString         docBackup;
+static QCString         briefBackup;
 
 //-----------------------------------------------------------------------------
 
@@ -475,6 +478,58 @@ static void prependScope()
   }
 }
 
+/*! Returns TRUE iff the current entry could be a K&R style C function */
+static bool checkForKnRstyleC()
+{
+  if (((QCString)yyFileName).right(2)!=".c") return FALSE; // must be a C file
+  if (!current->argList) return FALSE;
+  ArgumentListIterator ali(*current->argList);
+  Argument *a;
+  for (ali.toFirst();(a=ali.current());++ali)
+  {
+    // in K&R style argument do not have a type, but doxygen expects a type
+    // so it will think the argument has no name
+    if (a->type.isEmpty() || !a->name.isEmpty()) return FALSE;
+  }
+  return TRUE;
+}
+
+/*! Update the argument \a name with additional \a type info. For K&R style
+ *  function the type is found \e after the argument list, so this routine
+ *  in needed to fix up.
+ */
+void addKnRArgInfo(const QCString &type,const QCString &name,
+                   const QCString &brief,const QCString &docs)
+{
+  if (current->argList==0) return;
+  ArgumentListIterator ali(*current->argList);
+  Argument *a;
+  for (ali.toFirst();(a=ali.current());++ali)
+  {
+    if (a->type==name)
+    {
+      a->type=type.stripWhiteSpace();
+      if (a->type.left(9)=="register ") // strip keyword
+      {
+	a->type=a->type.mid(9);
+      }
+      a->name=name.stripWhiteSpace();
+      if (!brief.isEmpty() && !docs.isEmpty())
+      {
+        a->docs=brief+"\n\n"+docs;
+      }
+      else if (!brief.isEmpty())
+      {
+        a->docs=brief;
+      }
+      else
+      {
+	a->docs=docs;
+      }
+    }
+  }
+}
+
 /* ----------------------------------------------------------------- */
 #undef	YY_INPUT
 #define	YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
@@ -662,6 +717,7 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
 %x	PreLineCtrl
 %x	DefinePHP
 %x	DefinePHPEnd
+%x	OldStyleArgs
 
 %%
 
@@ -1510,7 +1566,7 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
 <FindMembers>[*&]+			{ current->name += yytext ; 
   					  addType( current );
 					}
-<FindMembers,MemberSpec,Function,NextSemi,BitFields,ReadInitializer>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" {
+<FindMembers,MemberSpec,Function,NextSemi,BitFields,ReadInitializer,OldStyleArgs>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" {
   					  lineCount();
 					  if (current->bodyLine==-1)
 					    current->bodyLine=yyLineNr;
@@ -1540,7 +1596,7 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
 					    BEGIN(AfterDoc);
 					  }
   					}
-<MemberSpec,FindFields,FindMembers,NextSemi,BitFields,ReadInitializer>","{BN}*("/**"|"//!"|"/*!"|"///")"<" {
+<MemberSpec,FindFields,FindMembers,NextSemi,BitFields,ReadInitializer,OldStyleArgs>","{BN}*("/**"|"//!"|"/*!"|"///")"<" {
   					  lineCount();
 					  lastAfterDocContext = YY_START;
 					  afterDocTerminator = ',';
@@ -1568,7 +1624,7 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
 					    BEGIN(AfterDoc);
 					  }
   					}
-<DefineEnd,FindFields,FindFieldArg,ReadInitializer>{BN}*("/**"|"//!"|"/*!"|"///")"<" {
+<DefineEnd,FindFields,FindFieldArg,ReadInitializer,OldStyleArgs>{BN}*("/**"|"//!"|"/*!"|"///")"<" {
   					  lineCount();
 					  lastAfterDocContext = YY_START;
 					  if (YY_START==DefineEnd)
@@ -2351,6 +2407,15 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
   					  *copyArgString+=*yytext;
   					  fullArgString+=*yytext;
 					  stringToArgumentList(fullArgString,current->argList);
+
+					  /* remember the current documentation block, since
+					     we could overwrite it with the documentation of
+					     a function argument, which we then have to correct later
+					     on
+					   */
+					  docBackup = current->doc.copy();
+					  briefBackup = current->brief.copy();
+
 					  BEGIN( currentArgumentContext );
 					}
 	/* a special comment */
@@ -2536,7 +2601,9 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
 					}
   */
 <FuncQual>[{:;,]                        {
-                                          if ( strcmp(yytext,";")==0 && insidePHP && current->type.left(8) != "function" )
+                                          if ( strcmp(yytext,";")==0 && 
+					       insidePHP && 
+					       current->type.left(8) != "function" )
                                           {
                                             current->reset();
                                             initEntry();
@@ -2547,17 +2614,17 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
                                             unput(*yytext); BEGIN( Function );
                                           }
                                         }
-<FuncQual>{BN}*"const"{BN}*       	{ 
+<FuncQual>{BN}*"const"{BN}*       	{ // const member function
   					  lineCount() ; 
   					  current->args += " const "; 
 					  current->argList->constSpecifier=TRUE;
 					}
-<FuncQual>{BN}*"volatile"{BN}*    	{ 
+<FuncQual>{BN}*"volatile"{BN}*    	{ // volatile member function
   					  lineCount() ; 
   					  current->args += " volatile "; 
 					  current->argList->volatileSpecifier=TRUE;
 					}
-<FuncQual>{BN}*"="{BN}*"0"{BN}*  	{ 
+<FuncQual>{BN}*"="{BN}*"0"{BN}*  	{ // pure virtual member function
   					  lineCount() ; 
 					  current->args += " = 0"; 
 					  current->virt = Pure; 
@@ -2576,6 +2643,82 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
   					  lastCPPContext = YY_START;
   					  BEGIN(SkipCPP);
 					}	
+<FuncQual>"="				{ // typically a initialized function pointer
+                                          current->args += *yytext; 
+  					}
+<FuncQual>{ID}				{ // typically a K&R style C function
+					  if (checkForKnRstyleC())
+					  {
+					    fprintf(stderr,"===> got a K&R style function\n");
+                                            current->args = yytext; 
+					    oldStyleArgType.resize(0);
+					    BEGIN(OldStyleArgs);
+					  }
+					  else
+					  {
+                                            current->args += yytext; 
+					  }
+  					}
+<OldStyleArgs>[,;]			{
+  					  QCString oldStyleArgPtr;
+  					  QCString oldStyleArgName;
+  					  if (oldStyleArgType.isEmpty())
+					  {
+					    int l=current->args.length(),i=l-1,j;
+					    char c;
+					    while (i>=0 && isId(current->args.at(i))) i--;
+					    j=i+1;
+					    while (i>=0 && ((c=current->args.at(i))=='*' || isspace(c))) i--;
+					    i++;
+					    if (i!=l)
+					    {
+					      oldStyleArgType=current->args.left(i);
+					      oldStyleArgPtr=current->args.mid(i,j-i);
+					      oldStyleArgName=current->args.mid(j).stripWhiteSpace();
+					    }
+					    else
+					    {
+					      oldStyleArgName=current->args.copy().stripWhiteSpace();
+					    }
+					  }
+					  else
+					  {
+					    int l=current->args.length(),j=0;
+					    char c;
+					    while (j<l && ((c=current->args.at(j))=='*' || isspace(c))) j++;
+					    if (j>0)
+					    {
+					      oldStyleArgPtr=current->args.left(j);
+					      oldStyleArgName=current->args.mid(j).stripWhiteSpace();
+					    }
+					    else
+					    {
+					      oldStyleArgName=current->args.copy().stripWhiteSpace();
+					    }
+					  }
+					  fprintf(stderr,"type=%s ptr=%s name=%s\n",oldStyleArgType.data(),oldStyleArgPtr.data(),oldStyleArgName.data());
+					  QCString doc,brief;
+					  if (current->doc!=docBackup)
+					  {
+                                            doc=current->doc.copy();
+					    current->doc=docBackup;
+					  }
+					  if (current->brief!=briefBackup)
+					  {
+                                            brief=current->brief.copy();
+					    current->brief=briefBackup;
+					  }
+					  addKnRArgInfo(oldStyleArgType+oldStyleArgPtr,oldStyleArgName,brief,doc);
+					  current->args.resize(0);
+					  if (*yytext==';') oldStyleArgType.resize(0);
+  					}
+<OldStyleArgs>{ID} 			{ current->args += yytext; }
+<OldStyleArgs>"{"			{
+  					  current->args = argListToString(current->argList);
+  					  unput('{');
+					  BEGIN(FuncQual);
+  					}
+<OldStyleArgs>.	 			{ current->args += *yytext; }
 <FuncQual,FuncRound,FuncFunc>.		{ current->args += *yytext; }
 <FuncQual>{BN}*"try"{BN}+		{ /* try-function-block */ 
 					  insideTryBlock=TRUE;
@@ -3140,7 +3283,7 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
 					}
 <Comment>.				{ current->program += *yytext ; }
 
-<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases>("//"{B}*)?"/*!" { 
+<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/*!" { 
   					  //printf("Start doc block at %d\n",yyLineNr);
 					  removeSlashes=(yytext[1]=='/');
 					  tmpDocType=-1;
@@ -3161,7 +3304,7 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
                                           }
 					  BEGIN( Doc );
 					}
-<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases>("//"{B}*)?"/**"/[^/*] {
+<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/**"/[^/*] {
   					  removeSlashes=(yytext[1]=='/');
 					  lastDocContext = YY_START;
 					  //printf("Found comment block at %s:%d\n",yyFileName,yyLineNr);
@@ -3212,7 +3355,7 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
 					    }
 					  }
   					}
-<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases>"//!" { 
+<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" { 
                                           if (YY_START!=SkipCurly)
 					  {
   					    current->brief.resize(0);
@@ -3231,7 +3374,7 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
                                           }
 					  BEGIN( LineDoc );
 					}
-<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases>"///"/[^/] { 
+<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] { 
                                           if (YY_START!=SkipCurly)
 					  {
   					    current->brief.resize(0);
@@ -4367,13 +4510,15 @@ PHPKW	  ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;]
 					  }
   					}
 <SkipSection>"*/"			{
-  					  unput('/');unput('*');
-					  BEGIN( lastIfContext );
+					  BEGIN( SkipSection );
+  					}
+<SkipSection>"/*!"			{
+					  BEGIN( SkipSection );
   					}
 <SkipSection>\n				{
   					  yyLineNr++;
   					}
-<SkipSection>"//"|"*/"			  					
+<SkipSection>"//"|"*/"
 <ClassDoc,ClassDocBrief,LineDoc,AfterDocLine,AfterDocBrief,Doc,JavaDoc,AfterDoc,PageDoc,ExampleDoc>{CMD}"elseif"/[^a-z_A-Z0-9] {
                                           // previous section enabled => skip now
   					  depthIf=1;
diff --git a/src/search.php b/src/search.php
index 29bbc7a..7075ea3 100644
--- a/src/search.php
+++ b/src/search.php
@@ -193,6 +193,10 @@ function filter_results($docs,&$requiredWords,&$forbiddenWords)
 
 function compare_rank($a,$b)
 {
+  if ($a["rank"] == $b["rank"]) 
+  {
+    return 0;
+  }
   return ($a["rank"]>$b["rank"]) ? -1 : 1; 
 }
 
diff --git a/src/search_php.h b/src/search_php.h
index 7f24842..4213b19 100644
--- a/src/search_php.h
+++ b/src/search_php.h
@@ -193,6 +193,10 @@
 "\n"
 "function compare_rank($a,$b)\n"
 "{\n"
+"  if ($a[\"rank\"] == $b[\"rank\"]) \n"
+"  {\n"
+"    return 0;\n"
+"  }\n"
 "  return ($a[\"rank\"]>$b[\"rank\"]) ? -1 : 1; \n"
 "}\n"
 "\n"
diff --git a/src/translator_kr.h b/src/translator_kr.h
index bdf1e5e..f94dcb6 100644
--- a/src/translator_kr.h
+++ b/src/translator_kr.h
@@ -26,7 +26,7 @@
 #ifndef TRANSLATOR_KR_H
 #define TRANSLATOR_KR_H
 
-class TranslatorKorean : public TranslatorAdapter_1_3
+class TranslatorKorean : public Translator
 {
   public:
 
-- 
cgit v0.12

