Index: trunk/Assembly_Library/Src/LibraryTests.asm
===================================================================
--- trunk/Assembly_Library/Src/LibraryTests.asm	(revision 45)
+++ trunk/Assembly_Library/Src/LibraryTests.asm	(revision 46)
@@ -33,8 +33,8 @@
 	CALL_DISPLAY_LIBRARY ClearScreen
 
-	call	LibraryTests_Sort
+	;call	LibraryTests_Sort
 	;call	LibraryTests_ForDisplayLibrary
 	;call	LibraryTests_ForKeyboardLibrary
-	;call	LibraryTests_ForMenuLibrary
+	call	LibraryTests_ForMenuLibrary
 
 	; Exit to DOS
@@ -571,9 +571,9 @@
 	push	ax
 	mov		ax, [si]
-	;DISPLAY_DEBUG_CHARACTER 'I'
-	;DISPLAY_DEBUG_WORD_AND_WAIT_ANY_KEY ax, 10
-	;DISPLAY_DEBUG_CHARACTER ','
-	;DISPLAY_DEBUG_WORD_AND_WAIT_ANY_KEY [es:di], 10
-	;DISPLAY_DEBUG_CHARACTER ' '
+	DISPLAY_DEBUG_CHARACTER 'I'
+	DISPLAY_DEBUG_WORD_AND_WAIT_ANY_KEY ax, 16
+	DISPLAY_DEBUG_CHARACTER ','
+	DISPLAY_DEBUG_WORD_AND_WAIT_ANY_KEY [es:di], 16
+	DISPLAY_DEBUG_CHARACTER ' '
 	cmp		ax, [es:di]
 	pop		ax
@@ -586,5 +586,5 @@
 	pop		ds
 	mov		si, .rgwItems
-	mov		bx, 10
+	mov		bx, 16
 .Loop:
 	lodsw
@@ -596,11 +596,11 @@
 
 .rgwItems:
-	dw		435
-	dw		-31551
-	dw		345
-	dw		0
-	dw		-18
-	dw		23
-	dw		435
+	dw		'['
+	dw		'n'
+	dw		'5'
+	dw		'.'
+	dw		']'
+	dw		'a'
+	dw		'A'
 
 
Index: trunk/Assembly_Library/Src/Menu/Dialog/Dialog.asm
===================================================================
--- trunk/Assembly_Library/Src/Menu/Dialog/Dialog.asm	(revision 45)
+++ trunk/Assembly_Library/Src/Menu/Dialog/Dialog.asm	(revision 46)
@@ -2,5 +2,5 @@
 ; Project name	:	Assembly Library
 ; Created date	:	6.8.2010
-; Last update	:	27.9.2010
+; Last update	:	1.10.2010
 ; Author		:	Tomi Tilli
 ; Description	:	Common functions for many dialogs.
@@ -28,6 +28,6 @@
 	eENTER_STRUCT DIALOG_size
 
-	mov		cx, DIALOG_size / 2
-	call	Memory_ZeroSSBPbyWordsInCX
+	mov		cx, DIALOG_size
+	call	Memory_ZeroSSBPwithSizeInCX
 	mov		[bp+DIALOG.fpDialogIO], si
 	mov		[bp+DIALOG.fpDialogIO+2], ds
Index: trunk/Assembly_Library/Src/Menu/Dialog/DialogFile.asm
===================================================================
--- trunk/Assembly_Library/Src/Menu/Dialog/DialogFile.asm	(revision 45)
+++ trunk/Assembly_Library/Src/Menu/Dialog/DialogFile.asm	(revision 46)
@@ -2,5 +2,5 @@
 ; Project name	:	Assembly Library
 ; Created date	:	6.9.2010
-; Last update	:	28.9.2010
+; Last update	:	4.10.2010
 ; Author		:	Tomi Tilli
 ; Description	:	Displays file dialog.
@@ -112,4 +112,6 @@
 	call	LoadItemStringBufferToESDI
 	call	CreateStringFromCurrentDirectoryContentsToESDI
+	call	LoadItemStringBufferToESDI
+	call	SortDirectoryContentsStringFromESDIwithCountInCX
 	push	ss
 	pop		ds
@@ -120,5 +122,7 @@
 	CALL_DISPLAY_LIBRARY GetColumnsToALandRowsToAH
 	mov		[bp+MENUINIT.bHeight], ah				; Always max height
-	mov		WORD [bp+MENU.wHighlightedItem], 0
+	xor		ax, ax
+	mov		[bp+MENU.wHighlightedItem], ax
+	mov		[bp+MENU.wFirstVisibleItem], ax
 	ret
 
@@ -146,7 +150,7 @@
 ;		SS:BP:	Ptr to DIALOG
 ;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		AX, CX, DX, SI, DI, DS, ES
+;		CX:		Number of files or directories found
+;	Corrupts registers:
+;		AX, DX, SI, DI, DS, ES
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
@@ -160,4 +164,5 @@
 	call	Directory_GetDiskTransferAreaAddressToDSSI
 	rcl		cx, 1			; Restore CF
+	xor		cx, cx			; Clear file/directory count
 	; Fall to .FindMatchingFilesAndWriteThemToESDI
 
@@ -165,15 +170,16 @@
 ; .FindMatchingFilesAndWriteThemToESDI
 ;	Parameters:
+;		CX:		Initial directory count
 ;		DL:		Zero if root directory selected
 ;		DS:SI:	Ptr to DTA with first matching file
 ;		ES:DI:	Ptr to destination string buffer
 ;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		AX, CX, DX, DI
+;		CX:		Incremented by number of files/directories found
+;	Corrupts registers:
+;		AX, DX, DI
 ;--------------------------------------------------------------------
 ;ALIGN JUMP_ALIGN
 .FindMatchingFilesAndWriteThemToESDI:
-	jc		SHORT RemoveLastLFandTerminateESDIwithNull
+	jc		SHORT TerminateESDIwithNull
 	call	AppendFileToBufferInESDIfromDtaInDSSI
 	call	Directory_UpdateDTAForNextMatchUsingPreviousParameters
@@ -200,6 +206,7 @@
 	ret
 
-;--------------------------------------------------------------------
-; RemoveLastLFandTerminateESDIwithNull
+
+;--------------------------------------------------------------------
+; TerminateESDIwithNull
 ;	Parameters:
 ;		ES:DI:	Ptr to destination string buffer
@@ -210,20 +217,22 @@
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-RemoveLastLFandTerminateESDIwithNull:
+TerminateESDIwithNull:
 	xor		ax, ax
-	dec		di				; Remove last LF
 	stosb
 	ret
 
+
 ;--------------------------------------------------------------------
 ; AppendFileToBufferInESDIfromDtaInDSSI
 ;	Parameters:
+;		CX:		Files/directores found
 ;		DL:		Zero if root directory selected
 ;		DS:SI:	Ptr to DTA containing file information
 ;		ES:DI:	Ptr to destination string buffer
 ;	Returns:
+;		CX:		Incremented by number of files/directories found
 ;		DI:		Updated for next file
 ;	Corrupts registers:
-;		AX, BX, CX, DX
+;		AX, BX, DX
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
@@ -231,4 +240,5 @@
 	call	.FilterCurrentDirectory			; We never want "."
 	call	.FilterUpDirectoryWhenInRoot	; No ".." when in root directory
+	inc		cx								; Nothing filtered so increment files/directories
 	; Fall to .PrepareBufferFormattingAndFormatFromDTAinDSSI
 
@@ -241,5 +251,5 @@
 ;		DI:		Updated for next file
 ;	Corrupts registers:
-;		AX, BX, CX, DX
+;		AX, BX, DX
 ;--------------------------------------------------------------------
 ;ALIGN JUMP_ALIGN
@@ -247,9 +257,10 @@
 	push	bp
 	push	si
-	mov		cx, di
+	push	cx
+	mov		bx, di
 	CALL_DISPLAY_LIBRARY PushDisplayContext
 
+	xchg	ax, bx
 	mov		bx, es
-	xchg	ax, cx
 	CALL_DISPLAY_LIBRARY SetCharacterPointerFromBXAX
 	mov		bl, ATTRIBUTES_NOT_USED
@@ -261,7 +272,8 @@
 	CALL_DISPLAY_LIBRARY GetCharacterPointerToBXAX
 	mov		es, bx
-	xchg	cx, ax
+	xchg	bx, ax
 	CALL_DISPLAY_LIBRARY PopDisplayContext
-	mov		di, cx
+	mov		di, bx
+	pop		cx
 	pop		si
 	pop		bp
@@ -281,10 +293,29 @@
 	mov		bp, sp
 	lea		ax, [si+DTA.szFile]
-	push	ax
-	push	ds
 
 	test	BYTE [si+DTA.bFileAttributes], FLG_FILEATTR_DIRECTORY
 	jnz		SHORT .FormatDirectory
-
+	; Fall to .FormatFile
+
+;--------------------------------------------------------------------
+; .FormatFile
+;	Parameters:
+;		BP:		SP before pushing formatting parameters
+;		DS:AX:	Far pointer to file name
+;		DS:SI:	Ptr to DTA containing file information
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI, BP
+;--------------------------------------------------------------------
+.FormatFile:
+	; Push parameters for file name
+	xchg	si, ax
+	call	String_ConvertDSSItoLowerCase
+	xchg	ax, si
+	push	ax				; Push directory name offset
+	push	ds				; Push directory name segment
+
+	; Push parameters for file size
 	mov		ax, [si+DTA.dwFileSize]
 	mov		dx, [si+DTA.dwFileSize+2]
@@ -298,9 +329,24 @@
 	push	dx
 	push	cx
+
+	; Format to buffer
 	mov		si, g_szFileFormat
 	jmp		SHORT .FormatStringInCSSIandReturn
 
+;--------------------------------------------------------------------
+; .FormatDirectory
+;	Parameters:
+;		BP:		SP before pushing formatting parameters
+;		DS:AX:	Far pointer to directory name
+;		DS:SI:	Ptr to DTA containing file information
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI, BP
+;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
 .FormatDirectory:
+	push	ax				; Push directory name offset
+	push	ds				; Push directory name segment
 	mov		ax, g_szSub
 	cmp		WORD [si+DTA.szFile], UPDIR_CHARACTERS
@@ -345,4 +391,67 @@
 
 ;--------------------------------------------------------------------
+; SortDirectoryContentsStringFromESDIwithCountInCX
+;	Parameters:
+;		CX:		Number of files and directories
+;		ES:DI:	Buffer containing directory contents string
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI, DS, ES
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+SortDirectoryContentsStringFromESDIwithCountInCX:
+	call	Memory_ExchangeDSSIwithESDI
+	mov		bx, .FileStringComparator
+	xchg	dx, cx
+	mov		cx, FILE_STRING_LENGTH
+	jmp		Sort_ItemsFromDSSIwithCountInDXsizeInCXandComparatorInBX
+
+;--------------------------------------------------------------------
+; .FileStringComparator
+;	Parameters:
+;		CX:		Item size in bytes
+;		DS:SI:	Ptr to first item to compare
+;		ES:DI:	Ptr to second item to compare
+;	Returns:
+;		FLAGS:	Signed comparition between first and second item
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.FileStringComparator:
+	push	di
+	push	si
+	push	cx
+	push	bx
+
+	mov		bx, FILE_STRING_LENGTH-2			; Zero BH
+	cmp		WORD [si], UPDIR_CHARACTERS
+	je		SHORT .ForceValueFromDSSItoBeLess
+	mov		bl, [si+bx]
+	cmp		bl, [es:di+FILE_STRING_LENGTH-2]	; 'B' for files, 'R' for directories
+	jne		SHORT .ForceValueFromDSSItoBeMoreOrLess
+	repe cmpsb									; Two directories or two files
+
+ALIGN JUMP_ALIGN
+.ReturnFromComparison:
+	pop		bx
+	pop		cx
+	pop		si
+	pop		di
+	ret
+ALIGN JUMP_ALIGN
+.ForceValueFromDSSItoBeMoreOrLess:
+	ja		SHORT .ForceValueFromDSSItoBeLess	; Directory in SI, file in DI
+	xchg	bl, bh
+	; Fall to ForceValueFromDSSItoBeLess
+ALIGN JUMP_ALIGN
+.ForceValueFromDSSItoBeLess:
+	cmp		bh, bl
+	jmp		SHORT .ReturnFromComparison
+
+
+;--------------------------------------------------------------------
 ; GetInfoLinesToCXandDialogFlagsToAX
 ;	Parameters:
@@ -388,12 +497,15 @@
 ALIGN JUMP_ALIGN
 ParseSelectionFromItemLineInDSSI:
-	cmp		BYTE [si], '['
-	je		SHORT .ChangeToSubdirInDSSI
-	; Fall to .SelectFileFromDSSI
-
-;--------------------------------------------------------------------
-; .SelectFileFromDSSI
-;	Parameters:
-;		DS:SI:	Ptr to char buffer containing file name to be selected
+	mov		ax, [si]
+	cmp		ax, UPDIR_CHARACTERS
+	je		SHORT .ChangeToUpdir
+	call	Char_IsUpperCaseLetterInAL
+	jc		SHORT .ParseAndChangeToSubdirInDSSI
+	; Fall to .ParseAndSelectFileFromDSSI
+
+;--------------------------------------------------------------------
+; .ParseAndSelectFileFromDSSI
+;	Parameters:
+;		DS:SI:	NULL terminated string selected from dialog
 ;		SS:BP:	Ptr to DIALOG
 ;	Returns:
@@ -402,6 +514,5 @@
 ;		All, except BP
 ;--------------------------------------------------------------------
-;ALIGN JUMP_ALIGN
-.SelectFileFromDSSI:
+.ParseAndSelectFileFromDSSI:
 	les		di, [bp+DIALOG.fpDialogIO]
 	add		di, BYTE FILE_DIALOG_IO.szFile
@@ -414,19 +525,31 @@
 
 ;--------------------------------------------------------------------
-; ChangeToSubdirInDSSI
-;	Parameters:
-;		DS:SI:	NULL terminated string containing new subdir in []
-;		SS:BP:	Ptr to DIALOG
-;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		All, except BP
-;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-.ChangeToSubdirInDSSI:
-	inc		si					; Skip '['
-	mov		BYTE [si+12], NULL	; Replace ']' with NULL
-	cmp		WORD [si], UPDIR_CHARACTERS
-	eCMOVE	si, g_szUpdir		; Real DOS do not accept spaces after ".."
+; .ChangeToUpdir
+;	Parameters:
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ChangeToUpdir:
+	mov		si, g_szUpdir
+	jmp		SHORT .ChangeDirectoryToDSSI
+
+;--------------------------------------------------------------------
+; .ParseAndChangeToSubdirInDSSI
+;	Parameters:
+;		DS:SI:	NULL terminated string selected from dialog
+;		SS:BP:	Ptr to DIALOG
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		All, except BP
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+.ParseAndChangeToSubdirInDSSI:
+	mov		BYTE [si+12], NULL	; Terminate with NULL (unnecessary spaces do not matter)
+.ChangeDirectoryToDSSI:
 	call	Directory_ChangeToPathFromDSSI
 	; Fall to RefreshFilesToDisplay
@@ -624,5 +747,5 @@
 	or		bx, cx
 	jnz		SHORT .BitShiftLoop
-	jmp		RemoveLastLFandTerminateESDIwithNull
+	jmp		TerminateESDIwithNull
 
 ;--------------------------------------------------------------------
Index: trunk/Assembly_Library/Src/Menu/Dialog/LineSplitter.asm
===================================================================
--- trunk/Assembly_Library/Src/Menu/Dialog/LineSplitter.asm	(revision 45)
+++ trunk/Assembly_Library/Src/Menu/Dialog/LineSplitter.asm	(revision 46)
@@ -2,5 +2,5 @@
 ; Project name	:	Assembly Library
 ; Created date	:	8.8.2010
-; Last update	:	15.9.2010
+; Last update	:	1.10.2010
 ; Author		:	Tomi Tilli
 ; Description	:	Splits long strings to multiple lines.
@@ -131,5 +131,5 @@
 .ProcessControlCharacter:
 	cmp		al, NULL			; End of string?
-	je		SHORT .EndOfString
+	je		SHORT .RemoveEmptyLinesAtTheEndIfAnyExists
 	cmp		al, LF				; Line feed?
 	je		SHORT .NewlineCharacter
@@ -142,11 +142,22 @@
 ALIGN JUMP_ALIGN
 .NewlineCharacter:
-	mov		BYTE [si-1], SOH					; SOH marks previous newline character
+	mov		BYTE [si-1], SOH	; SOH marks previous newline character
 	mov		[bp+LINE_SPLITTER.pLastWord], si
 	jmp		SHORT .StartNewLine
 
 ALIGN JUMP_ALIGN
-.EndOfString:
-	ret
+.RemoveEmptyLinesAtTheEndIfAnyExists:
+	mov		al, [si-2]			; Load character before NULL
+	cmp		al, SOH
+	je		SHORT .RemoveEmptyLineAtTheEndOfString
+	cmp		al, LF
+	je		SHORT .RemoveEmptyLineAtTheEndOfString
+	ret
+ALIGN JUMP_ALIGN
+.RemoveEmptyLineAtTheEndOfString:
+	dec		si
+	dec		WORD [bp+LINE_SPLITTER.wLines]
+	mov		BYTE [si-1], NULL
+	jmp		SHORT .RemoveEmptyLinesAtTheEndIfAnyExists
 
 
Index: trunk/Assembly_Library/Src/Menu/Dialog/StringsForDialogs.asm
===================================================================
--- trunk/Assembly_Library/Src/Menu/Dialog/StringsForDialogs.asm	(revision 45)
+++ trunk/Assembly_Library/Src/Menu/Dialog/StringsForDialogs.asm	(revision 46)
@@ -2,5 +2,5 @@
 ; Project name	:	Assembly Library
 ; Created date	:	14.9.2010
-; Last update	:	27.9.2010
+; Last update	:	1.10.2010
 ; Author		:	Tomi Tilli
 ; Description	:	Strings used by dialogs.
@@ -22,12 +22,13 @@
 	db		"Enter name for new file or directory.",NULL
 
+FILE_STRING_LENGTH		EQU		(24+1)	; +1 = LF in directory contents string
 g_szFileFormat:
-	db		"%14S  %4-u %c%cB",LF,NULL
+	db		"%16S%4-u %c%cB",LF,NULL
 g_szDirectoryFormat:
-	db		"[%12S]  %s-DIR",LF,NULL
+	db		"%16S%s-DIR",LF,NULL
 g_szSub:
 	db		ANGLE_QUOTE_RIGHT,"SUB",NULL
 g_szUp:
-	db		ANGLE_QUOTE_LEFT,"UP",NULL
+	db		ANGLE_QUOTE_LEFT," UP",NULL
 
 g_szSingleItem:			; Used by Dialog.asm for single item line
Index: trunk/Assembly_Library/Src/Menu/MenuAttributes.asm
===================================================================
--- trunk/Assembly_Library/Src/Menu/MenuAttributes.asm	(revision 45)
+++ trunk/Assembly_Library/Src/Menu/MenuAttributes.asm	(revision 46)
@@ -94,5 +94,5 @@
 istruc ATTRIBUTE_CHARS
 	at	ATTRIBUTE_CHARS.cBordersAndBackground,	db	COLOR_ATTRIBUTE(COLOR_BRIGHT_WHITE, COLOR_BLACK)
-	at	ATTRIBUTE_CHARS.cShadow,				db	COLOR_ATTRIBUTE(COLOR_GRAY, COLOR_WHITE)
+	at	ATTRIBUTE_CHARS.cShadow,				db	COLOR_ATTRIBUTE(COLOR_GRAY, COLOR_BLACK)
 	at	ATTRIBUTE_CHARS.cTitle,					db	COLOR_ATTRIBUTE(COLOR_BRIGHT_WHITE, COLOR_BLACK)
 	at	ATTRIBUTE_CHARS.cItem,					db	COLOR_ATTRIBUTE(COLOR_WHITE, COLOR_BLACK)
Index: trunk/Assembly_Library/Src/Menu/MenuInit.asm
===================================================================
--- trunk/Assembly_Library/Src/Menu/MenuInit.asm	(revision 45)
+++ trunk/Assembly_Library/Src/Menu/MenuInit.asm	(revision 46)
@@ -2,5 +2,5 @@
 ; Project name	:	Assembly Library
 ; Created date	:	13.7.2010
-; Last update	:	16.9.2010
+; Last update	:	1.10.2010
 ; Author		:	Tomi Tilli
 ; Description	:	Functions for initializing menu system.
@@ -27,6 +27,6 @@
 	eENTER_STRUCT MENU_size
 
-	mov		cx, MENU_size / 2
-	call	Memory_ZeroSSBPbyWordsInCX
+	mov		cx, MENU_size
+	call	Memory_ZeroSSBPwithSizeInCX
 	call	MenuInit_EnterMenuWithHandlerInBXandUserDataInDXAX
 	mov		ax, [bp+MENU.wHighlightedItem]
Index: trunk/Assembly_Library/Src/String/String.asm
===================================================================
--- trunk/Assembly_Library/Src/String/String.asm	(revision 45)
+++ trunk/Assembly_Library/Src/String/String.asm	(revision 46)
@@ -2,5 +2,5 @@
 ; Project name	:	Assembly Library
 ; Created date	:	12.7.2010
-; Last update	:	6.9.2010
+; Last update	:	1.10.2010
 ; Author		:	Tomi Tilli
 ; Description	:	Functions for handling characters.
@@ -76,2 +76,32 @@
 	pop		ax
 	ret
+
+
+;--------------------------------------------------------------------
+; String_ConvertDSSItoLowerCase
+;	Parameters:
+;		DS:SI:	Ptr to NULL terminated string to convert
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+String_ConvertDSSItoLowerCase:
+	push	si
+	push	ax
+
+ALIGN JUMP_ALIGN
+.ConvertNextCharacter:
+	lodsb
+	test	al, al				; NULL to end string?
+	jz		SHORT .EndOfString
+	call	Char_ALtoLowerCaseLetter
+	mov		[si-1], al
+	jmp		SHORT .ConvertNextCharacter
+
+ALIGN JUMP_ALIGN
+.EndOfString:
+	pop		ax
+	pop		si
+	ret
Index: trunk/Assembly_Library/Src/Util/Memory.asm
===================================================================
--- trunk/Assembly_Library/Src/Util/Memory.asm	(revision 45)
+++ trunk/Assembly_Library/Src/Util/Memory.asm	(revision 46)
@@ -2,5 +2,5 @@
 ; Project name	:	Assembly Library
 ; Created date	:	14.7.2010
-; Last update	:	15.9.2010
+; Last update	:	1.10.2010
 ; Author		:	Tomi Tilli
 ; Description	:	Functions for memory access.
@@ -10,23 +10,53 @@
 
 ;--------------------------------------------------------------------
-; Memory_ZeroDSSIbyWordsInCX
+; OPTIMIZE_STRING_OPERATION
 ;	Parameters
-;		CX:		Number of words to zero
-;		DS:SI:	Ptr to buffer to zero
+;		%1:		Repeat instruction
+;		%2:		String instruction without size (for example MOVS and not MOVSB or MOVSW)
+;		CX:		Number of BYTEs to operate
+;		DS:SI:	Ptr to source data
+;		ES:DI:	Ptr to destination
 ;	Returns:
+;		SI, DI:	Updated by number of bytes operated
+;	Corrupts registers:
 ;		Nothing
+;--------------------------------------------------------------------
+%macro OPTIMIZE_STRING_OPERATION 2
+	push	cx
+
+	shr		cx, 1			; Operate with WORDs for performance
+	jcxz	%%HandleRemainingByte
+	%1		%2w
+%%HandleRemainingByte:
+	jnc		SHORT %%OperationCompleted
+	%2b
+
+ALIGN JUMP_ALIGN
+%%OperationCompleted:
+	pop		cx
+%endmacro
+
+
+;--------------------------------------------------------------------
+; Memory_CopyCXbytesFromDSSItoESDI
+;	Parameters
+;		CX:		Number of bytes to copy
+;		DS:SI:	Ptr to source data
+;		ES:DI:	Ptr to destination buffer
+;	Returns:
+;		SI, DI:	Updated by number of bytes copied
 ;	Corrupts registers:
-;		AX
+;		Nothing
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-Memory_ZeroDSSIbyWordsInCX:
-	call	Memory_ExchangeDSSIwithESDI
-	call	Memory_ZeroESDIbyWordsInCX
-	jmp		SHORT Memory_ExchangeDSSIwithESDI
+Memory_CopyCXbytesFromDSSItoESDI:
+	OPTIMIZE_STRING_OPERATION rep, movs
+	ret
+
 
 ;--------------------------------------------------------------------
-; Memory_ZeroSSBPbyWordsInCX
+; Memory_ZeroSSBPwithSizeInCX
 ;	Parameters
-;		CX:		Number of words to zero
+;		CX:		Number of bytes to zero
 ;		SS:BP:	Ptr to buffer to zero
 ;	Returns:
@@ -36,24 +66,19 @@
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-Memory_ZeroSSBPbyWordsInCX:
-	push	es
-	push	di
+Memory_ZeroSSBPwithSizeInCX:
 	push	ax
 
-	push	ss
-	pop		es
-	mov		di, bp
-	call	Memory_ZeroESDIbyWordsInCX
+	call	Memory_ExchangeSSBPwithESDI
+	call	Memory_ZeroESDIwithSizeInCX
+	call	Memory_ExchangeSSBPwithESDI
 
 	pop		ax
-	pop		di
-	pop		es
 	ret
 
 ;--------------------------------------------------------------------
-; Memory_ZeroESDIbyWordsInCX
+; Memory_ZeroESDIwithSizeInCX
 ;	Parameters
-;		CX:		Number of words to zero
-;		ES:DI:	Ptr to buffer to zero
+;		CX:		Number of bytes to zero
+;		ES:DI:	Ptr to destination buffer
 ;	Returns:
 ;		Nothing
@@ -62,14 +87,14 @@
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-Memory_ZeroESDIbyWordsInCX:
+Memory_ZeroESDIwithSizeInCX:
 	xor		ax, ax
-	; Fall to Memory_FillESDIwithAXbyCXtimes
+	; Fall to Memory_StoreCXbytesFromAccumToESDI
 
 ;--------------------------------------------------------------------
-; Memory_FillESDIwithAXbyCXtimes
+; Memory_StoreCXbytesFromAccumToESDI
 ;	Parameters
 ;		AX:		Word to use to fill buffer
-;		CX:		Number of words to fill
-;		ES:DI:	Ptr to buffer to fill
+;		CX:		Number of BYTEs to store
+;		ES:DI:	Ptr to destination buffer
 ;	Returns:
 ;		Nothing
@@ -78,23 +103,29 @@
 ;--------------------------------------------------------------------
 ALIGN JUMP_ALIGN
-Memory_FillESDIwithAXbyCXtimes:
-	cld
-	push	di
-	push	cx
-	rep stosw
-	pop		cx
-	pop		di
+Memory_StoreCXbytesFromAccumToESDI:
+	OPTIMIZE_STRING_OPERATION rep, stos
+	sub		di, cx
 	ret
 
 
 ;--------------------------------------------------------------------
+; Memory_ExchangeSSBPwithESDI
 ; Memory_ExchangeDSSIwithESDI
 ;	Parameters
 ;		Nothing
 ;	Returns:
-;		DS:SI and ES:DI are exchanged.
+;		SS:BP/DS:SI and ES:DI are exchanged.
 ;	Corrupts registers:
 ;		Nothing
 ;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+Memory_ExchangeSSBPwithESDI:
+	xchg	bp, di
+	push	ss
+	push	es
+	pop		ss
+	pop		es
+	ret
+
 ALIGN JUMP_ALIGN
 Memory_ExchangeDSSIwithESDI:
@@ -108,20 +139,12 @@
 
 ;--------------------------------------------------------------------
-; Memory_CopySSBPtoDSSI
 ; Memory_CopySSBPtoESDI
 ;	Parameters
 ;		Nothing
 ;	Returns:
-;		DS:SI:		Same as SS:BP
+;		ES:DI:		Same as SS:BP
 ;	Corrupts registers:
 ;		Nothing
 ;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
-Memory_CopySSBPtoDSSI:
-	push	ss
-	pop		ds
-	mov		si, bp
-	ret
-
 ALIGN JUMP_ALIGN
 Memory_CopySSBPtoESDI:
Index: trunk/Assembly_Library/Src/Util/Sort.asm
===================================================================
--- trunk/Assembly_Library/Src/Util/Sort.asm	(revision 45)
+++ trunk/Assembly_Library/Src/Util/Sort.asm	(revision 46)
@@ -2,5 +2,5 @@
 ; Project name	:	Assembly Library
 ; Created date	:	28.9.2010
-; Last update	:	29.9.2010
+; Last update	:	1.10.2010
 ; Author		:	Tomi Tilli
 ; Description	:	Sorting algorithms
@@ -9,6 +9,6 @@
 
 struc QSORT_PARAMS
-	.lpItems		resb	4
-	.tempStruct:
+	.lpItems			resb	4
+	.tempAndPivotItems:
 endstruc
 
@@ -16,6 +16,7 @@
 ; Prototype for comparator callback function
 ;	Parameters:
-;		DS:SI:	Offset to first item to compare
-;		ES:DI:	Offset to second item to compare
+;		CX:		Item size in bytes
+;		DS:SI:	Ptr to first item to compare
+;		ES:DI:	Ptr to second item to compare
 ;	Returns:
 ;		FLAGS:	Signed comparition between first and second item
@@ -29,8 +30,10 @@
 
 ;--------------------------------------------------------------------
-; DialogFile_GetFileNameWithIoInDSSI
-;	Parameters:
-;		DS:SI:	Ptr to FILE_DIALOG_IO
-;		SS:BP:	Ptr to parent MENU
+; Sort_ItemsFromDSSIwithCountInDXsizeInCXandComparatorInBX
+;	Parameters:
+;		CX:		Item size in bytes
+;		DX:		Number of items to sort (signed)
+;		CS:BX:	Comparator function
+;		DS:SI:	Ptr to array of items to sort
 ;	Returns:
 ;		Nothing
@@ -42,10 +45,13 @@
 	push	es
 	push	di
+	mov		di, cx
+	shl		cx, 1						; Reserve temp and pivot items
 	add		cx, BYTE QSORT_PARAMS_size
 	eENTER_STRUCT cx
+	push	cx
 
 	cld
-	sub		cx, BYTE QSORT_PARAMS_size	; Restore CX to item size
-	xor		ax, ax						; Zero for starting index
+	mov		cx, di						; Restore item size to CX
+	xor		ax, ax						; Zero starting index
 	dec		dx							; Count to index of last item
 	mov		[bp+QSORT_PARAMS.lpItems], si
@@ -54,6 +60,6 @@
 
 	lds		si, [bp+QSORT_PARAMS.lpItems]
-	add		cx, BYTE QSORT_PARAMS_size
-	eLEAVE_STRUCT cx
+	pop		ax
+	eLEAVE_STRUCT ax
 	pop		di
 	pop		es
@@ -86,5 +92,5 @@
 	; Does left partition need more sorting
 	cmp		si, dx			; if (first index < Index of rightmost unsorted item)
-	jae		SHORT .CheckIfRightPartitionNeedsMoreSorting
+	jge		SHORT .CheckIfRightPartitionNeedsMoreSorting
 	xchg	ax, si			; AX = first index, SI = Index of leftmost unsorted item
 	call	QuicksortItemsInRangeFromAXtoDXwithQsortParamsInSSBP
@@ -93,5 +99,5 @@
 .CheckIfRightPartitionNeedsMoreSorting:
 	cmp		ax, di			; if (Index of leftmost unsorted item < last index)
-	jae		SHORT .SortCompleted
+	jge		SHORT .SortCompleted
 	mov		dx, di			; DI = Index of leftmost unsorted item
 	call	QuicksortItemsInRangeFromAXtoDXwithQsortParamsInSSBP
@@ -133,9 +139,15 @@
 .GetPivotPointerToESDI:
 	push	ax
+
 	add		ax, dx
-	shr		ax, 1
+	shr		ax, 1			; AX = Middle index in partition
 	call	GetItemPointerToDSSIfromIndexInAX
+	call	GetPointerToTemporaryItemToESDI
+	add		di, cx			; Pivot is after temporary item
+	call	CopyItemFromDSSItoESDI
+	sub		di, cx			; Restore DI
+
 	pop		ax
-	jmp		Memory_ExchangeDSSIwithESDI
+	ret
 
 
@@ -158,5 +170,5 @@
 ArrangeItemsInRangeAXtoDXtoBothSidesOfPivotInESDI:
 	cmp		ax, dx	; while (left <= right)
-	ja		SHORT .BreakLoopSinceAllItemsExamined
+	jg		SHORT .BreakLoopSinceAllItemsExamined
 
 	call	GetItemPointerToDSSIfromIndexInAX
@@ -167,5 +179,5 @@
 
 	cmp		ax, dx	; If (left <= right)
-	ja		SHORT ArrangeItemsInRangeAXtoDXtoBothSidesOfPivotInESDI
+	jg		SHORT ArrangeItemsInRangeAXtoDXtoBothSidesOfPivotInESDI
 	call	SwapItemsFromIndexesAXandDX
 	inc		ax
@@ -213,17 +225,17 @@
 
 	; Item AX to stack
-	call	.GetPtrToTemporaryStructToESDI
+	call	GetPointerToTemporaryItemToESDI
 	call	GetItemPointerToDSSIfromIndexInAX
-	call	.CopyItemFromDSSItoESDI
+	call	CopyItemFromDSSItoESDI
 
 	; Item DX to Item AX
 	call	Memory_ExchangeDSSIwithESDI
 	call	GetItemPointerToDSSIfromIndexInDX
-	call	.CopyItemFromDSSItoESDI
+	call	CopyItemFromDSSItoESDI
 
 	; Stack to Item DX
-	call	.GetPtrToTemporaryStructToESDI
+	call	GetPointerToTemporaryItemToESDI
 	call	Memory_ExchangeDSSIwithESDI
-	call	.CopyItemFromDSSItoESDI
+	call	CopyItemFromDSSItoESDI
 
 	pop		di
@@ -231,25 +243,19 @@
 	ret
 
-ALIGN JUMP_ALIGN
-.GetPtrToTemporaryStructToESDI:
-	lea		di, [bp+QSORT_PARAMS.tempStruct]
+
+;--------------------------------------------------------------------
+; GetPointerToTemporaryItemToESDI
+;	Parameters:
+;		SS:BP:	Ptr to QSORT_PARAMS
+;	Returns:
+;		ES:DI:	Ptr to temporary item
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+GetPointerToTemporaryItemToESDI:
+	lea		di, [bp+QSORT_PARAMS.tempAndPivotItems]
 	push	ss
 	pop		es
-	ret
-
-ALIGN JUMP_ALIGN
-.CopyItemFromDSSItoESDI:
-	push	si
-	push	cx
-
-	shr		cx, 1			; We want to copy WORDs for performance
-	jcxz	.CopyLastByte
-	rep		movsw
-.CopyLastByte:
-	jnc		SHORT .CopyComplete
-	movsb
-.CopyComplete:
-	pop		cx
-	pop		si
 	ret
 
@@ -286,2 +292,20 @@
 	pop		dx
 	ret
+
+
+;--------------------------------------------------------------------
+; CopyItemFromDSSItoESDI
+;	Parameters:
+;		CX:		Item size in bytes
+;		DS:SI:	Ptr to source item
+;		ES:DI:	Ptr to destination buffer
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		DI
+;--------------------------------------------------------------------
+ALIGN JUMP_ALIGN
+CopyItemFromDSSItoESDI:
+	call	Memory_CopyCXbytesFromDSSItoESDI
+	sub		si, cx			; Restore SI
+	ret
