Release 960818

Sun Aug 18 12:17:54 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [files/drive.c]
	Added 'Filesystem' option in drives configuration.

	* [files/dos_fs.c] 
	Added handling of case-insensitive filesystems.

	* [memory/selector.c] [include/stackframe.h]
	Removed MAKE_SEGPTR.

	* [misc/commdlg.c] [multimedia/mcistring.c]
	Replaced MAKE_SEGPTR by the SEGPTR_* macros.

	* [objects/bitblt.c] [windows/graphics.c]
	Use an intermediary pixmap to avoid some BadMatch errors on
	XGetImage().

Sun Aug 18 09:21:27 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [windows/message.c]
	Added handling of WM_NC...mouse messages in JOURNALRECORD hook.

	* [misc/ver.c]
	Fixed a bad string result in VerQueryValue[16|32A|32W].

Fri Aug 16 19:55:04 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [if1632/crtdll.spec] [misc/crtdll.c]
	More additions to get win95 programs further down the road.

	* [if1632/kernel.spec] [loader/module.c]
	GetModuleName() added.
	LoadModule(): params->showCmd can be NULL.

	* [if1632/kernel32.spec] [if1632/thunk.c]
	ThunkConnect32() stub added.

	* [loader/resource.c]
	Entries include lastentry.

	* [misc/shell.c] [files/file.c]
	Made progman work again.

Fri Aug 16 09:00:00 1996  Alex Korobka <alex@phm30.pharm.sunysb.edu>
	
	* [windows/defwnd.c] [windows/winpos.c] [windows/painting.c]
	Icon painting fixes.

	* [windows/winpos.c] [windows/painting.c]
	Enforce and follow hrgnUpdate more closely to cut down on
	redundant RedrawWindow() calls.

	* [windows/event.c]
	Process ConfigureNotify only for managed windows.

	* [windows/winpos.c]
	Do not redraw parent if the window was hidden before SetWindowPos().

	* [windows/nonclient.c]
	Omit some nonclient decoration painting for managed windows.

	* [controls/menu.c] [windows/mdi.c] [windows/nonclient.c]
	Implemented WM_NEXTMENU.

	* [controls/listbox.c]
	Multicolumn listboxes return WVR_VREDRAW on WM_NCCALCSIZE.

	* [misc/shell.c]
	Added .ICO file handling to ExtractIcon().
diff --git a/files/dos_fs.c b/files/dos_fs.c
index e0a1e17..376368a 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -63,10 +63,11 @@
  * (i.e. contains only valid DOS chars, lower-case only, fits in 8.3 format).
  * File name can be terminated by '\0', '\\' or '/'.
  */
-static int DOSFS_ValidDOSName( const char *name )
+static int DOSFS_ValidDOSName( const char *name, int ignore_case )
 {
-    static const char invalid_chars[] = INVALID_DOS_CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    static const char invalid_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" INVALID_DOS_CHARS;
     const char *p = name;
+    const char *invalid = ignore_case ? (invalid_chars + 26) : invalid_chars;
     int len = 0;
 
     if (*p == '.')
@@ -79,7 +80,7 @@
     }
     while (!IS_END_OF_NAME(*p))
     {
-        if (strchr( invalid_chars, *p )) return 0;  /* Invalid char */
+        if (strchr( invalid, *p )) return 0;  /* Invalid char */
         if (*p == '.') break;  /* Start of the extension */
         if (++len > 8) return 0;  /* Name too long */
         p++;
@@ -90,7 +91,7 @@
     len = 0;
     while (!IS_END_OF_NAME(*p))
     {
-        if (strchr( invalid_chars, *p )) return 0;  /* Invalid char */
+        if (strchr( invalid, *p )) return 0;  /* Invalid char */
         if (*p == '.') return 0;  /* Second extension not allowed */
         if (++len > 3) return 0;  /* Extension too long */
         p++;
@@ -280,7 +281,7 @@
  * hashed version that fits in 8.3 format.
  * File name can be terminated by '\0', '\\' or '/'.
  */
-const char *DOSFS_Hash( const char *name, int dir_format )
+const char *DOSFS_Hash( const char *name, int dir_format, int ignore_case )
 {
     static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
     static const char hash_chars[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
@@ -293,7 +294,7 @@
 
     if (dir_format) strcpy( buffer, "           " );
 
-    if (DOSFS_ValidDOSName( name ))
+    if (DOSFS_ValidDOSName( name, ignore_case ))
     {
         /* Check for '.' and '..' */
         if (*name == '.')
@@ -322,10 +323,19 @@
         /* Compute the hash code of the file name */
         /* If you know something about hash functions, feel free to */
         /* insert a better algorithm here... */
-        for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
-            hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
-        hash = (hash << 3) ^ (hash >> 5) ^ *p;  /* Last character */
-        
+        if (ignore_case)
+        {
+            for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
+                hash = (hash << 3) ^ (hash >> 5) ^ tolower(*p) ^ (tolower(p[1]) << 8);
+            hash = (hash << 3) ^ (hash >> 5) ^ tolower(*p); /* Last character*/
+        }
+        else
+        {
+            for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
+                hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
+            hash = (hash << 3) ^ (hash >> 5) ^ *p;  /* Last character */
+        }
+
         /* Find last dot for start of the extension */
         for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++)
             if (*p == '.') ext = p;
@@ -368,7 +378,7 @@
  * Return 1 if OK, 0 if no file name matches.
  */
 static int DOSFS_FindUnixName( const char *path, const char *name,
-                               char *buffer, int maxlen )
+                               char *buffer, int maxlen, UINT32 drive_flags )
 {
     DIR *dir;
     struct dirent *dirent;
@@ -390,12 +400,22 @@
     while ((dirent = readdir( dir )) != NULL)
     {
         /* Check against Unix name */
-        if ((len == strlen(dirent->d_name) &&
-             !memcmp( dirent->d_name, name, len ))) break;
+        if (len == strlen(dirent->d_name))
+        {
+            if (drive_flags & DRIVE_CASE_SENSITIVE)
+            {
+                if (!lstrncmp32A( dirent->d_name, name, len )) break;
+            }
+            else
+            {
+                if (!lstrncmpi32A( dirent->d_name, name, len )) break;
+            }
+        }
         if (dos_name)
         {
             /* Check against hashed DOS name */
-            const char *hash_name = DOSFS_Hash( dirent->d_name, TRUE );
+            const char *hash_name = DOSFS_Hash( dirent->d_name, TRUE,
+                                       !(drive_flags & DRIVE_CASE_SENSITIVE) );
             if (!strcmp( dos_name, hash_name )) break;
         }
     }
@@ -445,6 +465,7 @@
 {
     static char buffer[MAX_PATHNAME_LEN];
     int drive, len, found;
+    UINT32 flags;
     char *p, *root;
 
     dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: %s\n", name );
@@ -470,6 +491,7 @@
         DOS_ERROR( ER_InvalidDrive, EC_MediaError, SA_Abort, EL_Disk );
         return NULL;
     }
+    flags = DRIVE_GetFlags(drive);
     lstrcpyn32A( buffer, DRIVE_GetRoot(drive), MAX_PATHNAME_LEN );
     if (buffer[1]) root = buffer + strlen(buffer);
     else root = buffer;  /* root directory */
@@ -502,7 +524,7 @@
             DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
             return NULL;
         }
-        if ((found = DOSFS_FindUnixName( buffer, name, p+1, len-1 )))
+        if ((found = DOSFS_FindUnixName( buffer, name, p+1, len-1, flags )))
         {
             *p = '/';
             len -= strlen(p);
@@ -548,6 +570,7 @@
 {
     static char buffer[MAX_PATHNAME_LEN];
     int drive, len;
+    UINT32 flags;
     char *p;
 
     dprintf_dosfs( stddeb, "DOSFS_GetDosTrueName(%s,%d)\n", name, unix_format);
@@ -589,6 +612,7 @@
     }
     *p = '\0';
     len = MAX_PATHNAME_LEN - (int)(p - buffer);
+    flags = DRIVE_GetFlags(drive);
 
     while (*name)
     {
@@ -607,7 +631,9 @@
         *p++ = '\\';
         if (unix_format)  /* Hash it into a DOS name */
         {
-            lstrcpyn32A( p, DOSFS_Hash( name, FALSE ), len );
+            lstrcpyn32A( p, DOSFS_Hash( name, FALSE,
+                                     !(flags & DRIVE_CASE_SENSITIVE) ),
+                         len );
             len -= strlen(p);
             p += strlen(p);
             while (!IS_END_OF_NAME(*name)) name++;
@@ -651,7 +677,8 @@
     static int drive_root = 0;
     char *p;
     const char *hash_name;
-    
+    UINT32 flags;
+
     if ((attr & ~(FA_UNUSED | FA_ARCHIVE | FA_RDONLY)) == FA_LABEL)
     {
         if (skip) return 0;
@@ -686,12 +713,14 @@
     strcat( buffer, "/" );
     p = buffer + strlen(buffer);
     attr |= FA_UNUSED | FA_ARCHIVE | FA_RDONLY;
+    flags = DRIVE_GetFlags( drive );
 
     while ((dirent = readdir( dir )) != NULL)
     {
         if (skip-- > 0) continue;
         count++;
-        hash_name = DOSFS_Hash( dirent->d_name, TRUE );
+        hash_name = DOSFS_Hash( dirent->d_name, TRUE,
+                                !(flags & DRIVE_CASE_SENSITIVE) );
         if (!DOSFS_Match( mask, hash_name )) continue;
         /* Don't return '.' and '..' in the root of the drive */
         if (drive_root && (dirent->d_name[0] == '.') &&
@@ -708,6 +737,7 @@
         if (entry->attr & ~attr) continue;
         strcpy( entry->name, hash_name );
         lstrcpyn32A( entry->unixname, dirent->d_name, sizeof(entry->unixname));
+        if (!(flags & DRIVE_CASE_PRESERVING)) AnsiLower( entry->unixname );
         dprintf_dosfs( stddeb, "DOSFS_FindNext: returning %s %02x %ld\n",
                        entry->name, entry->attr, entry->size );
         cur_pos += count;
@@ -730,7 +760,7 @@
     dprintf_dosfs( stddeb, "GetShortPathName32A(%s,%p,%ld)\n",
                    longpath, shortpath, shortlen );
 
-    dostruename = DOSFS_GetDosTrueName( longpath, 0 );
+    dostruename = DOSFS_GetDosTrueName( longpath, TRUE );
     lstrcpyn32A( shortpath, dostruename, shortlen );
     return strlen(dostruename);
 }
@@ -742,7 +772,7 @@
 DWORD GetShortPathName32W( LPCWSTR longpath, LPWSTR shortpath, DWORD shortlen )
 {
     LPSTR longpatha = STRING32_DupUniToAnsi( longpath );
-    LPCSTR dostruename = DOSFS_GetDosTrueName( longpatha, 0 );
+    LPCSTR dostruename = DOSFS_GetDosTrueName( longpatha, TRUE );
     free( longpatha );
     lstrcpynAtoW( shortpath, dostruename, shortlen );
     return strlen(dostruename);