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

Last change on this file since 46 was 46, checked in by aitotat, 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.