source: xtideuniversalbios/trunk/Assembly_Library/Src/Menu/Dialog/LineSplitter.asm@ 50

Last change on this file since 50 was 46, checked in by Tomi Tilli, 14 years ago

Changes to Assembly Library:
Sorting now works (pivot item is copied for comparison and index comparisons are now signed instead of unsigned).
Menu shadow now looks better on black and white modes.
Sorting is now implemented for File Fialog: directories are displayed before files.
File Dialog now displays directories with upper case letters and files with lower case letters.
Line splitter now removes all empty lines from the end.

File size: 6.8 KB
Line 
1; File name : Line Splitter.asm
2; Project name : Assembly Library
3; Created date : 8.8.2010
4; Last update : 1.10.2010
5; Author : Tomi Tilli
6; Description : Splits long strings to multiple lines.
7
8struc LINE_SPLITTER
9 .pLastWord resb 2
10 .wMaxLineLength resb 2
11 .wLines resb 2
12endstruc
13
14
15; Section containing code
16SECTION .text
17
18;--------------------------------------------------------------------
19; LineSplitter_SplitStringFromDSSIwithMaxLineLengthInAXandGetLineCountToAX
20; Parameters:
21; AX: Maximum allowed length for a line
22; DS:SI: Ptr to string to split
23; Returns:
24; AX: Number of lines
25; Corrupts registers:
26; CX, SI
27;--------------------------------------------------------------------
28ALIGN JUMP_ALIGN
29LineSplitter_SplitStringFromDSSIwithMaxLineLengthInAXandGetLineCountToAX:
30 xor cx, cx
31 cmp [si], cl ; String length zero?
32 jne SHORT .PrepareToSplit
33 xchg ax, cx
34 ret
35
36ALIGN JUMP_ALIGN
37.PrepareToSplit:
38 eENTER_STRUCT LINE_SPLITTER_size ; SS:BP now points to LINE_SPLITTER
39
40 mov [bp+LINE_SPLITTER.wLines], cx
41 call Memory_SetZFifNullPointerInDSSI
42 jz SHORT .ReturnNumberOfLinesInAX
43 call SplitStringFromDSSIusingLineSplitterInSSBP
44
45.ReturnNumberOfLinesInAX:
46 mov ax, [bp+LINE_SPLITTER.wLines]
47 eLEAVE_STRUCT LINE_SPLITTER_size
48 ret
49
50;--------------------------------------------------------------------
51; SplitStringFromDSSIusingLineSplitterInSSBP
52; Parameters:
53; AX: Maximum allowed length for a line
54; DS:SI: Ptr to string to split
55; SS:BP: Ptr to LINE_SPLITTER
56; Returns:
57; SS:BP: Ptr to LINE_SPLITTER with number of lines
58; Corrupts registers:
59; AX, CX, SI
60;--------------------------------------------------------------------
61ALIGN JUMP_ALIGN
62SplitStringFromDSSIusingLineSplitterInSSBP:
63 mov [bp+LINE_SPLITTER.pLastWord], si
64 mov [bp+LINE_SPLITTER.wMaxLineLength], ax
65 inc WORD [bp+LINE_SPLITTER.wLines] ; Always at least one line
66 xor cx, cx ; Length of current line
67 cld
68ALIGN JUMP_ALIGN
69.ScanNextCharacter:
70 lodsb ; Load from [DS:SI] to AL, increment SI
71 cmp al, ' ' ; Control character or space?
72 je SHORT .ProcessSpace
73 jb SHORT .ProcessControlCharacter
74.IncrementCharacterCount:
75 inc cx ; Increment character count
76 cmp cx, [bp+LINE_SPLITTER.wMaxLineLength]
77 jbe SHORT .ScanNextCharacter
78
79 mov si, [bp+LINE_SPLITTER.pLastWord] ; Resume to beginning of last word
80 mov BYTE [si-1], STX ; STX marks start or new line
81 ; Fall to .StartNewLine
82
83;--------------------------------------------------------------------
84; .StartNewLine
85; Parameters:
86; CX: Line length so far
87; DS:SI: Ptr character that begins new line
88; SS:BP: Ptr to LINE_SPLITTER
89; Returns:
90; CX: Zero
91; SS:BP: LINE_SPLITTER updated for number of lines
92; Jumps to .ScanNextCharacter
93; Corrupts registers:
94; Nothing
95;--------------------------------------------------------------------
96.StartNewLine:
97 inc WORD [bp+LINE_SPLITTER.wLines] ; Increment number of lines
98 xor cx, cx ; Zero line length
99 jmp SHORT .ScanNextCharacter
100
101;--------------------------------------------------------------------
102; .ProcessSpace
103; Parameters:
104; CX: Line length so far
105; DS:SI: Ptr first character after space
106; SS:BP: Ptr to LINE_SPLITTER
107; Returns:
108; SS:BP: LINE_SPLITTER updated to beginning of next word
109; Jumps to .IncrementCharacterCount
110; Corrupts registers:
111; Nothing
112;--------------------------------------------------------------------
113ALIGN JUMP_ALIGN
114.ProcessSpace:
115 mov [bp+LINE_SPLITTER.pLastWord], si
116 jmp SHORT .IncrementCharacterCount
117
118;--------------------------------------------------------------------
119; .ProcessControlCharacter
120; Parameters:
121; AL: Control character
122; CX: Line length so far
123; DS:SI: Ptr inside string to split
124; SS:BP: Ptr to LINE_SPLITTER
125; Returns:
126; SS:BP: LINE_SPLITTER updated to beginning of next line (LF control character)
127; Corrupts registers:
128; Nothing
129;--------------------------------------------------------------------
130ALIGN JUMP_ALIGN
131.ProcessControlCharacter:
132 cmp al, NULL ; End of string?
133 je SHORT .RemoveEmptyLinesAtTheEndIfAnyExists
134 cmp al, LF ; Line feed?
135 je SHORT .NewlineCharacter
136 cmp al, SOH ; Previous newline character?
137 je SHORT .NewlineCharacter
138
139 mov BYTE [si-1], ' ' ; Replace unhandled control characters with space
140 jmp SHORT .ProcessSpace
141
142ALIGN JUMP_ALIGN
143.NewlineCharacter:
144 mov BYTE [si-1], SOH ; SOH marks previous newline character
145 mov [bp+LINE_SPLITTER.pLastWord], si
146 jmp SHORT .StartNewLine
147
148ALIGN JUMP_ALIGN
149.RemoveEmptyLinesAtTheEndIfAnyExists:
150 mov al, [si-2] ; Load character before NULL
151 cmp al, SOH
152 je SHORT .RemoveEmptyLineAtTheEndOfString
153 cmp al, LF
154 je SHORT .RemoveEmptyLineAtTheEndOfString
155 ret
156ALIGN JUMP_ALIGN
157.RemoveEmptyLineAtTheEndOfString:
158 dec si
159 dec WORD [bp+LINE_SPLITTER.wLines]
160 mov BYTE [si-1], NULL
161 jmp SHORT .RemoveEmptyLinesAtTheEndIfAnyExists
162
163
164;--------------------------------------------------------------------
165; LineSplitter_PrintLineInCXfromStringInESDI
166; Parameters:
167; CX: Index of line to print
168; ES:DI: Ptr to string containing the line
169; Returns:
170; Nothing
171; Corrupts registers:
172; AX, BX, SI
173;--------------------------------------------------------------------
174ALIGN JUMP_ALIGN
175LineSplitter_PrintLineInCXfromStringInESDI:
176 push di
177 push cx
178
179 call LineSplitter_GetOffsetToSIforLineCXfromStringInESDI
180 jnc SHORT .LineNotFound
181 mov bx, es
182 CALL_DISPLAY_LIBRARY PrintCharBufferFromBXSIwithLengthInCX
183.LineNotFound:
184 pop cx
185 pop di
186 ret
187
188
189;--------------------------------------------------------------------
190; LineSplitter_GetOffsetToSIforLineCXfromStringInESDI
191; Parameters:
192; CX: Index of line to search for
193; ES:DI: Ptr to string
194; Returns:
195; CX: Line length
196; ES:SI: Ptr to beginning of line
197; CF: Set if wanted line was found
198; Corrupts registers:
199; AX, DI
200;--------------------------------------------------------------------
201ALIGN JUMP_ALIGN
202LineSplitter_GetOffsetToSIforLineCXfromStringInESDI:
203 mov si, di ; SI points to start of first line
204 mov al, STX ; Last control character to scan for
205 inc cx ; Increment CX to get length for first line
206 cld
207ALIGN JUMP_ALIGN
208.LineScanLoop:
209 scasb ; cmp al, [es:di]. Increment DI
210 jb SHORT .LineScanLoop ; Non control character
211
212 ; Our end of line characters or NULL character
213 dec cx ; Decrement lines to scan through
214 jz SHORT .WantedLineFound
215 cmp BYTE [es:di-1], NULL
216 je SHORT .EndOfString ; Jump with CF cleared
217 mov si, di ; SI points to start of new line
218 jmp SHORT .LineScanLoop
219
220ALIGN JUMP_ALIGN
221.WantedLineFound:
222 stc ; Set CF since wanted line was found
223.EndOfString:
224 lahf ; Load FLAGS low to AH
225 lea cx, [di-1] ; We don't want control character to be printed
226 sub cx, si ; String length to CX
227 sahf ; Store AH to FLAGS low
228 ret
Note: See TracBrowser for help on using the repository browser.