update dev300-m58
[ooovba.git] / testautomation / global / tools / includes / optional / t_listfuncs.inc
blob4934a29759e3fa7c6924c17e289e6ce5aaecbeb9
1 'encoding UTF-8  Do not remove or change this line!
2 '**************************************************************************
3 '* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 '* 
5 '* Copyright 2008 by Sun Microsystems, Inc.
6 '*
7 '* OpenOffice.org - a multi-platform office productivity suite
8 '*
9 '* $RCSfile: t_listfuncs.inc,v $
11 '* $Revision: 1.1 $
13 '* last change: $Author: jsk $ $Date: 2008-06-20 07:58:28 $
15 '* This file is part of OpenOffice.org.
17 '* OpenOffice.org is free software: you can redistribute it and/or modify
18 '* it under the terms of the GNU Lesser General Public License version 3
19 '* only, as published by the Free Software Foundation.
21 '* OpenOffice.org is distributed in the hope that it will be useful,
22 '* but WITHOUT ANY WARRANTY; without even the implied warranty of
23 '* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 '* GNU Lesser General Public License version 3 for more details
25 '* (a copy is included in the LICENSE file that accompanied this code).
27 '* You should have received a copy of the GNU Lesser General Public License
28 '* version 3 along with OpenOffice.org.  If not, see
29 '* <http://www.openoffice.org/license.html>
30 '* for a copy of the LGPLv3 License.
32 '/******************************************************************************
34 '* owner : joerg.skottke@sun.com
36 '* short description : Replacements for routines in t_lists.inc adds some
38 '*******************************************************************************
40 ' #1 hListTestUpperBoundary ' Tests upper boundary of arrays
41 ' #1 hListTestLowerBoundary ' Tests lower boundary of arrays
42 ' #1 hListDelete            ' Deletes one item from a list by index
43 ' #1 hListAppend            ' Append an item to a list
44 ' #1 hManageComparisionList ' quick way to compare/create reference lists
45 ' #1 hListFileGetSize       ' find out how big an array has to be to hold the file
46 ' #1 hListCompare           ' compare two lists
47 ' #1 hListPrependString     ' Insert a string infront of each item in a list
48 ' #1 hListAppendList        ' Append one list to another
49 ' #1 hCountMatchesInList    ' Return count of occurrences of a string within a list
51 '\******************************************************************************
53 ' Note: These functions fix some minor bugs and introduce strict boundary
54 '       checking for the arrays we work with. The arrays must be compatible
55 '       to those from the "standard" list-functions. 
56 ' Why:  Two reasons:
58 '       1) When working with listboxes it might happen that they are empty (bug)
59 '          or contain more items than expected. In this case the tests would 
60 '          usually break. This is not desired as many testcases do not rely 
61 '          on the content of the listboxes. 
62 '          
63 '       2) This way eases the trouble of debugging huge amounts of arrays
64 '          like those in the installation test or anywhere else where we work 
65 '          with reference lists. This is a coding help.
67 '*******************************************************************************
69 function hListTestUpperBoundary( aList() as string ) as boolean
71     '///<h3>Verify that ListCount does not exceed upper boundary</h3>
72     '///<i>About listfunctions: All listfunctions rely on a special type of
73     '///+ array. This can be string arrays and - in some cases - numeric
74     '///+ arrays. What makes the arrays unique is that the first item which
75     '///+ has the index 0 contains the number of items in the list to be used,
76     '///+ anything that is stored beyond this number is ignored. This has three 
77     '///+ consequences: 1) all listfunctions that alter an array must update
78     '///+ the index stored in array(0) and 2) it is possible that the index
79     '///+ point beyond ubound of the array which will most likely cause a
80     '///+ runtime error. 3) Means that arrays may only have an upper boundary
81     '///+ declared, all loops must start with index array(1) and must end with
82     '///+ index array(val( array(0))</i><br>
83     '///<u>Input</u>:
84     '///<ol>
85     '///+<li>List (string)</li>
86     '///</ol>
87     '///<u>Returns</u>:
88     '///<ol>
89     '///+<li>Errorstatus (boolean)</li>
90     '///<ul>
91     '///+<li>TRUE: Array is ok</li>
92     '///+<li>FALSE: Array logic has errors</li>
93     '///</ul>
94     '///</ol>
95     '///<u>Description</u>:
96     '///<ul>
98     
99     const CFN = "hListTestUpperBoundary::"
100     
101     dim iUpperBoundary as integer ' size according to UBOUND
102     dim iListSize as integer  ' size according to ListCount
103     
104     dim brc as boolean
105         brc = true
106     
107     '///+<li>Determine the size of the array</li>
108     iUpperBoundary = UBOUND( aList() )
109     
110     '///+<li>Determine the <i>claimed</i> size of the array</li>
111     iListSize      = ListCount( aList() )
112     
113     '///+<li>Verify that val(array(0)) <= array-size</li>
114     if ( iListSize > iUpperBoundary ) then
115         warnlog ( CFN & "List points beyound upper array boundary:" )
116         printlog( CFN & "ListCount: " & iListSize  )
117         printlog( CFN & "UBOUND...: " & iUpperBoundary )
118         brc = false
119     endif
120     
121     hListTestUpperBoundary() = brc
122     '///</ul>
124 end function
126 '*******************************************************************************
128 function hListTestLowerBoundary( aList() as string ) as boolean
130     '///<h3>Verify that the lower boundaries of an array are ok</h3>
131     '///<i>Prerequisite: Array compatible with those from t_lists.inc</i>
132     '///<i>About listfunctions: All listfunctions rely on a special type of
133     '///+ array. This can be string arrays and - in some cases - numeric
134     '///+ arrays. What makes the arrays unique is that the first item which
135     '///+ has the index 0 contains the number of items in the list to be used,
136     '///+ anything that is stored beyond this number is ignored. This has three 
137     '///+ consequences: 1) all listfunctions that alter an array must update
138     '///+ the index stored in array(0) and 2) it is possible that the index
139     '///+ point beyond ubound of the array which will most likely cause a
140     '///+ runtime error. 3) Means that arrays may only have an upper boundary
141     '///+ declared, all loops must start with index array(1) and must end with
142     '///+ index array(val( array(0))</i><br>   
143     '///<u>Input</u>:
144     '///<ol>
145     '///+<li>List (string)</li>
146     '///</ol>
147     '///<u>Returns</u>:
148     '///<ol>
149     '///+<li>Errorstatus (boolean)</li>
150     '///<ul>
151     '///+<li>TRUE: Array is ok</li>
152     '///+<li>FALSE: Array logic has errors</li>
153     '///</ul>
154     '///</ol>
155     '///<u>Description</u>:
156     '///<ul>    
157     
158     const CFN = "hListTestLowerBoundary::"
159     
160     dim iLowerBoundary as integer ' size according to LBOUND
161     dim iListSize as integer  ' size according to ListCount
162     
163     dim brc as boolean
164         brc = true
165         
166     iLowerBoundary = LBOUND( aList() )
167     iListSize      = ListCount( aList() )   
168     
169     '///+<li>Verify that ubound for the array returns 0 (lower boundary)</li>
170     if ( iLowerBoundary <> 0 ) then
171         warnlog ( CFN & "Boundary of the array must be 0." )
172         printlog( CFN & "Lower boundary is: " & iLowerBoundary )
173         brc = false
174     endif
175     
176     '///+<li>Verify that val(array(0)) &gt; 0</li>
177     if ( iListSize < 0 ) then
178         warnlog ( CFN & "Defined Listsize (ListCount) may never be negative" )
179         printlog( CFN & "ListCount is: " & iListSize )
180         brc = false
181     endif
182    
183     hListTestLowerBoundary() = brc
184     '///</ul>
185     
186 end function
188 '*******************************************************************************
190 function hListDelete( aList() as string, iItemToDelete as integer ) as boolean
192     '///<h3>Delete one item from a list specified by index</h3>
193     '///<i>Prerequisite: Array compatible with those from t_lists.inc</i><br>
194     '///<i>About listfunctions: All listfunctions rely on a special type of
195     '///+ array. This can be string arrays and - in some cases - numeric
196     '///+ arrays. What makes the arrays unique is that the first item which
197     '///+ has the index 0 contains the number of items in the list to be used,
198     '///+ anything that is stored beyond this number is ignored. This has three 
199     '///+ consequences: 1) all listfunctions that alter an array must update
200     '///+ the index stored in array(0) and 2) it is possible that the index
201     '///+ point beyond ubound of the array which will most likely cause a
202     '///+ runtime error. 3) Means that arrays may only have an upper boundary
203     '///+ declared, all loops must start with index array(1) and must end with
204     '///+ index array(val( array(0))</i><br>    
205     '///<u>Review the code, it has many unused variables</u>
206     '///<ul>
208     const CFN = "hListDelete::"
210     dim iArraySize as integer   ' The size of the array, must be large enough
211     dim iListSizeOld as integer ' The size of the list before deletion
212     dim iListSizeNew as integer ' The size of the list after deletion
213     dim iCurrentItem as integer ' Increment-Variable
214     dim iOffset as integer      ' First item to be "moved down" by index
215     dim sItemToDelete as string ' The string that will be deleted
216     dim brc as boolean          ' preliminary return value
217     
218     '///+<li>test array integrity: upper boundary</li>
219     brc = hListTestUpperBoundary( alist() )
220     if ( not brc ) then
221         hListDelete() = brc
222         exit function
223     endif
224     
225     '///+<li>test array integrity: lower boundary</li>
226     brc = hListTestLowerBoundary( alist() )
227     if ( not brc ) then
228         hListDelete() = brc
229         exit function
230     endif    
231     
232     '///+<li>Get some data from the arrays to work with.</li>
233     iArraySize    = ubound( aList() )
234     iListSizeOld  = ListCount( aList() )
235     iListSizeNew  = iListSizeOld - 1
236     sItemToDelete = aList( iItemToDelete )
237     iOffset       = iItemToDelete + 1
238     
239     ' some output (may be removed as soon the function is thoroughly tested)
240     'printlog( CFN & "Removing: " & sItemToDelete & " at pos " & iItemToDelete )
241     
242     ' Move all items down by one in the list beginning with the item after
243     ' iItemToDelete
244     '///+<li>Move all items one up</li>
245     for iCurrentItem = iOffset to iListSizeOld
246         aList( iCurrentItem - 1 ) = aList( iCurrentItem )
247     next iCurrentItem
248     
249     ' Delete the last entry, it is no longer used and it is duplicate to the item
250     ' at iListSizeOld-1 (iListSizeNew)
251     '///+<li>Delete the last item from the list</li>
252     aList( iListSizeOld ) = ""
253     
254     '///+<li>Set the new listsize (one smaller than the original list)</li>
255     aList( 0 ) = iListSizeNew
256     '///</ul>
257     
258 end function
260 '*******************************************************************************
262 function hListAppend( sNewString as string, aTargetList() as string ) as integer
264     '///<h3>Append an item to an existing list</h3>
265     '///<i>Prerequisite: Array compatible with those from t_lists.inc</i>
266     '///<i>About listfunctions: All listfunctions rely on a special type of
267     '///+ array. This can be string arrays and - in some cases - numeric
268     '///+ arrays. What makes the arrays unique is that the first item which
269     '///+ has the index 0 contains the number of items in the list to be used,
270     '///+ anything that is stored beyond this number is ignored. This has three 
271     '///+ consequences: 1) all listfunctions that alter an array must update
272     '///+ the index stored in array(0) and 2) it is possible that the index
273     '///+ point beyond ubound of the array which will most likely cause a
274     '///+ runtime error. 3) Means that arrays may only have an upper boundary
275     '///+ declared, all loops must start with index array(1) and must end with
276     '///+ index array(val( array(0))</i><br>    
278     const CFN = "hListAppend::"
280     dim iCurrentListSize as integer
281     dim iNewListSize as integer
282     dim iArraySize as integer
283     dim irc as integer
285     iCurrentListSize = val( aTargetList( 0 ) )
286     iNewListSize = iCurrentListSize + 1
287     iArraySize = ubound( aTargetList() )
288     
289     if ( iNewListSize > iArraySize ) then
290         warnlog ( CFN & "Cannot append, array too small" )
291         printlog( CFN & "Array-Size.....: " & iArraySize )
292         printlog( CFN & "Requested index: " & iNewListSize )
293         irc = -1
294     else
295         aTargetList( iNewListSize ) = sNewString
296         aTargetList( 0 ) = iNewListSize
297         irc = iNewListSize
298     endif
299     
300     hListAppend() = irc
301     
302 end function
304 '*******************************************************************************
306 function hManageComparisionList( sFileIn as string, sFileOut as string, sListOut() as string ) as integer
308     '///<h3>Function to create or compare a list to a reference</h3>
309     '///<i>Prerequisite: List of items to compare, input- and outputfilename</i><br>
310     '///<i>About listfunctions: All listfunctions rely on a special type of
311     '///+ array. This can be string arrays and - in some cases - numeric
312     '///+ arrays. What makes the arrays unique is that the first item which
313     '///+ has the index 0 contains the number of items in the list to be used,
314     '///+ anything that is stored beyond this number is ignored. This has three 
315     '///+ consequences: 1) all listfunctions that alter an array must update
316     '///+ the index stored in array(0) and 2) it is possible that the index
317     '///+ point beyond ubound of the array which will most likely cause a
318     '///+ runtime error. 3) Means that arrays may only have an upper boundary
319     '///+ declared, all loops must start with index array(1) and must end with
320     '///+ index array(val( array(0))</i><br>    
321     '///<u>BEWARE: This is a core function and used by many tests!<br>
322     '///Please read the inline documentation for further reference</u><br>
323     '///Function parameters:
324     '///<ol>
325     '///+<li>sFileIn    = The file that contains the reference data</li>
326     '///+<li>sFileOut   = The file new lists are written to in case of an error</li>
327     '///+<li>sListOut() = The list containing the newly retrieved data.</li>
328     '///</ol>
329     '///Description:
330     '///<ul>
332     const CFN = "hManageComparisionList::"
333     
334     '///+<li>The name of the input file may not be empty</li>
335     if ( sFileIn = "" ) then
336         warnlog( CFN & "Invalid parameter: Input filename is empty string" )
337         hManageComparisionList() = 2
338         exit function
339     endif
340     
341     '///+<li>The name of the output-file may not be empty</li>
342     if ( sFileOut = "" ) then
343         warnlog( CFN & "Invalid parameter: Output filename is empty string" )
344         hManageComparisionList() = 3
345         exit function
346     endif    
347     
348     '///+<li>the list should not claim to be empty / be empty</li>
349     if ( listcount( sListOut() ) = 0 ) then
350         qaerrorlog( CFN & "Invalid parameter: Array claims to be empty" )
351         hManageComparisionList() = 4
352         exit function
353     endif   
354     
355     ' hListFileGetSize will return -1 if the list does not exist or the number
356     ' of lines in the reference file plus additional 10 lines.
357     '///+<li>Verify that the reference file exists and is non-empty</li>
358     dim iFileSize as integer
359         iFileSize = hListFileGetSize( sFileIn ) 
360     dim brc as boolean
361         brc = false
362     
363     '///+<li>Read the reference list and compare</li>
364     if ( iFileSize > -1 ) then
365     
366         dim aReferenceList( iFileSize ) as string
367         printlog( CFN & "Reading: " & sFileIn )
368         ' disabled hGetDataFileSection because some lists contain a #
369         ' (hash) as value which is identified as comment by the function.
370         ' Fixing this for hGetDataFileSection() would break compatibility
371         ' to other functions both in framework and global module
372         'hgetDataFileSection( sFileIn , aReferenceList() , "" , "" , "" )
373         listread( aReferenceList(), sFileIn, "utf8" )
374         brc = hListCompare( sListOut() , aReferenceList() )
375         
376     endif
377     
378     ' A this point there are three possible states:
379     ' a) the reference list does not exist
380     ' b) the comparision failed
381     ' c) the comparision succeeded
382     ' only if hListCompare() returns TRUE the testrun is successful.
383     ' This means that on any error, the ref-list will be written so it can be
384     ' directly reviewed/compared to the "faulty" list without having to run this
385     ' test again (after deleting the ref-file)
386     '///+<li>In case the lists are not identical, write the new one to the local work directory</li>
387     if ( brc ) then
388         printlog( CFN & "Comparision succeeded" )
389         hManageComparisionList() = 0    
390     else
391         printlog( CFN & "Writing: " & sFileOut )
392         listwrite( sListOut(), sFileOut, "UTF8" )
393         qaerrorlog ( CFN & "Reference file review required:" )
394         printlog( "" )
395         printlog( CFN & "Two possible reasons:" )
396         printlog( CFN & "1) The reference file does not exist at all" )
397         printlog( CFN & "2) Reference and actual UI-Content do not match." )
398         printlog( CFN & "Location: " & sFileOut )
399         printlog( CFN & "Target..: " & sFileIn  )
400         printlog( CFn & "Verify the content and copy the file to <Target>" )
401         printlog( "" )
402         printlog( CFN & "Comparision failed" )
403         hManageComparisionList() = 1
404     endif
405     
406     '///+<li>Return 0 if the lists are identical, 1 if not and 2-4 on any other error</li>
407     '///</ul>
409 end function
411 '*******************************************************************************
413 function hListFileGetSize( sFileIn as string ) as integer
415     '///<h3>Get the number of lines from a file</h3>
416     '///<i>Prerequisites: Path to an existing plain text file</i>
417     '///<i>About listfunctions: All listfunctions rely on a special type of
418     '///+ array. This can be string arrays and - in some cases - numeric
419     '///+ arrays. What makes the arrays unique is that the first item which
420     '///+ has the index 0 contains the number of items in the list to be used,
421     '///+ anything that is stored beyond this number is ignored. This has three 
422     '///+ consequences: 1) all listfunctions that alter an array must update
423     '///+ the index stored in array(0) and 2) it is possible that the index
424     '///+ point beyond ubound of the array which will most likely cause a
425     '///+ runtime error. 3) Means that arrays may only have an upper boundary
426     '///+ declared, all loops must start with index array(1) and must end with
427     '///+ index array(val( array(0))</i><br>    
428     '///<ul>
430     const CFN = "hListFileGetSize::"
431     const I_EXTRA_SIZE = 10
432     
433     '///+<li>Verify that the filename is non-empty</li>
434     if ( sFileIn = "" ) then
435         warnlog( CFN & "Invalid parameter: Filename is empty string" )
436         hListFileGetSize() = -1
437         exit function
438     endif
439     
440     '///+<li>Verify that the file exists</li>
441     if ( dir( sFileIn ) = "" ) then
442         warnlog( CFN & "File not found: " & sFileIn ) 
443         hListFileGetSize() = -1
444         exit function
445     endif
446     
447     dim iFile as integer
448     dim sLine as string
449     dim iLineCount as integer
450         iLineCount = 0
451     
452     '///+<li>Open the file (standard BASIC calls)</li>
453     iFile = freefile
454     open sFileIn for input as iFile
455     
456     '///+<li>Read the number of lines from the file</li>
457     while( not eof( iFile ) ) 
458     
459         line input #iFile, sLine
460         iLineCount = iLineCount + 1
461         
462     wend
463     
464     '///+<li>Close the file</li>
465     close #iFile 
466     
467     '///+<li>Return the number of lines read or -1 on error</li>
468     hListFileGetSize() = iLineCount + I_EXTRA_SIZE
469     '///</ul>
470     
471 end function
473 '*******************************************************************************
475 function hListCompare( aListOne() as String, aListTwo() as String ) as boolean
477     const CFN = "hListcompare::"
479     '///<h3>Compare two lists with each other, where <b>list TWO</b> is the reference</h3>
480     '///<i>Prerequisites: Two lists compatible with listfunctions</i><br>
481     '///<i>About listfunctions: All listfunctions rely on a special type of
482     '///+ array. This can be string arrays and - in some cases - numeric
483     '///+ arrays. What makes the arrays unique is that the first item which
484     '///+ has the index 0 contains the number of items in the list to be used,
485     '///+ anything that is stored beyond this number is ignored. This has three 
486     '///+ consequences: 1) all listfunctions that alter an array must update
487     '///+ the index stored in array(0) and 2) it is possible that the index
488     '///+ point beyond ubound of the array which will most likely cause a
489     '///+ runtime error. 3) Means that arrays may only have an upper boundary
490     '///+ declared, all loops must start with index array(1) and must end with
491     '///+ index array(val( array(0))</i><br>    
492     '///<u>Duplicates gCompare2Lists but does not print warnlogs, evaluate returncode instead</u>
493     '///<ul>
495     dim aOneOnlyList( ubound( aListOne() ) ) as string
496     dim aTwoOnlyList( ubound( aListTwo() ) ) as string
497     
498     dim iListOneIndex as integer
499     dim iListTwoIndex as integer
500     
501     dim iTwoOnlyListSize as integer
502     dim iListOneSize as integer
503     
504     dim bFound as boolean
505     dim brc as boolean     ' returncode: true only if lists are identical
506         brc = true
507     
508     '///+<li>Create a copy of list two so we do not change the original list</li>
509     ListCopy( aListTwo() , aTwoOnlyList() )
511     iTwoOnlyListSize = ListCount( aTwoOnlyList() )
512     iListOneSize = ListCount( aListOne() )
514     
515     '///+<li>Step through each item in list one</li>
516     for iListOneIndex = 1 to iListOneSize
517     
518         bFound = false
519     
520         '///+<li>Compare it to each item in list two</li>
521         for iListTwoIndex = 1 to iTwoOnlyListSize
522         
523             '///+<li>If the entries match, delete it from the TwoOnly list</li>
524             if ( aListOne( iListOneIndex ) = aTwoOnlyList( iListTwoIndex ) ) then
525             
526                 bFound = true
527                 aTwoOnlyList( iListTwoIndex ) = aTwoOnlyList( iTwoOnlyListSize )
528                 ' this breaks compatibility to listfunctions because the actual
529                 ' number of items is out of sync with listcount
530                 iTwoOnlyListSize  = iTwoOnlyListSize -1                 
531                 exit for
532                 
533             end if
534             
535         next iListTwoIndex
536         
537         '///+<li>If there is no match, the item exists in list one only -> copy</li>
538         if ( not bFound ) then
539             hListAppend( aListOne( iListOneIndex ), aOneOnlyList() )
540         end if
541         
542     next iListOneIndex
543     
544     ' restore compatibility to listfunctions so hListPrint() will not fail
545     aTwoOnlyList( 0 ) = iTwoOnlyListSize
546     
547     '///+<li>List all items that exist in List One only</li>
548     if ( ListCount( aOneOnlyList() ) > 0 ) then
549         printlog( CFN & "Objects have been added to the list" )
550         hListPrint( aOneOnlyList() , "Items found in list ONE only (NEW)" )
551         brc = false
552     end if
553         
554     '///+<li>List all items that exist in List Two only</li>
555     if ( ListCount( aTwoOnlyList() ) > 0 ) then
556         printlog( CFN & "Objects have been removed from the list" )
557         hListPrint( aTwoOnlyList() , "Items found in list TWO only (MISSING)" )
558         brc = false
559     end if
561     hListCompare() = brc
562     '///</ul>
563     
564 end function
566 '*******************************************************************************
568 function hListPrependString( aList() as string, cString as string ) as boolean
570     '///<h3>Insert a string infront of each item in a list</h3>
571     '///<i>Prerequisites: A list compatible with listfunctions</i><br>
572     '///<i>About listfunctions: All listfunctions rely on a special type of
573     '///+ array. This can be string arrays and - in some cases - numeric
574     '///+ arrays. What makes the arrays unique is that the first item which
575     '///+ has the index 0 contains the number of items in the list to be used,
576     '///+ anything that is stored beyond this number is ignored. This has three 
577     '///+ consequences: 1) all listfunctions that alter an array must update
578     '///+ the index stored in array(0) and 2) it is possible that the index
579     '///+ point beyond ubound of the array which will most likely cause a
580     '///+ runtime error. 3) Means that arrays may only have an upper boundary
581     '///+ declared, all loops must start with index array(1) and must end with
582     '///+ index array(val( array(0))</i><br><br>
583     '///<i>Note that the function alters the input list. If the list contains 
584     '///+ strings of the type &quot;MyString&quot; the items will be changed to
585     '///+ read &quot;Some Text : MyString&quot;</i><br>
586     '///<u>Input</u>:
587     '///<ol>
588     '///+<li>List (string)</li>
589     '///+<li>A text to be inserted infront of every item in the list</li>
590     '///</ol>
591     '///<u>Returns</u>:
592     '///<ol>
593     '///+<li>Errorcondition (boolean)</li>
594     '///<ul>
595     '///+<li>The returnvalue is currently undefined</li>
596     '///</ul>
597     '///</ol>
598     '///<u>Description</u>:
599     '///<ul>
600     
601     const CFN = "hListPrependString::"
602     dim iCurrentItem as integer
603     
604     '///+<li>Cycle through the list and insert a text infront of each item</li>
605     for iCurrentItem = 1 to listcount( aList() )
606     
607         aList( iCurrentItem ) = cString & " : " & aList( iCurrentItem )
608         
609     next iCurrentItem
610     
611     hListPrependString() = true
612     '///</ul>
613     
614 end function
616 '*******************************************************************************
618 function hListAppendList( aBaseList() as string, aListToAppend() as string ) as integer
620     '///<h3>Append one list to another</h3>
621     '///<i>Prerequisites: A list compatible with listfunctions</i><br>
622     '///<i>About listfunctions: All listfunctions rely on a special type of
623     '///+ array. This can be string arrays and - in some cases - numeric
624     '///+ arrays. What makes the arrays unique is that the first item which
625     '///+ has the index 0 contains the number of items in the list to be used,
626     '///+ anything that is stored beyond this number is ignored. This has three 
627     '///+ consequences: 1) all listfunctions that alter an array must update
628     '///+ the index stored in array(0) and 2) it is possible that the index
629     '///+ point beyond ubound of the array which will most likely cause a
630     '///+ runtime error. 3) Means that arrays may only have an upper boundary
631     '///+ declared, all loops must start with index array(1) and must end with
632     '///+ index array(val( array(0))</i><br><br>
633     '///<u>Input</u>:
634     '///<ol>
635     '///+<li>Target list (string)</li>
636     '///+<li>Source list (string)</li>
637     '///</ol>
638     '///<u>Returns</u>:
639     '///<ol>
640     '///+<li>Listsize (integer)</li>
641     '///<ul>
642     '///+<li>The size of the sum of both lists</li>
643     '///+<li>0 in case of error</li>
644     '///</ul>
645     '///</ol>
646     '///<u>Description</u>:
647     '///<ul>
648     
649     const CFN = "hListAppendList::"
650     
651     dim iCurrentItem as integer
652     dim iNewSize as integer
653     
654     '///+<li>Do some basic boundary checking</li>
655     if ( ubound( aBaseList() ) < _
656         ( listcount( aBaseList ) + listcount( aListToAppend() ) ) ) then
657         warnlog( CFN & "Base Array too small" )
658         iNewSize = 0
659     else
660     
661         '///+<li>Append the list</li>
662         for iCurrentItem = 1 to listcount( aListToAppend() ) 
663   
664             hListAppend( aBaseList() , aListToAppend( iCurrentItem ) )
665             
666         next iCurrentItem
667         
668         iNewSize = listcount( aBaseList() ) 
669         
670     endif
671     '///</ul>
673 end function
676 '*******************************************************************************
678 function hCountMatchesInList( acItemList() as string, cSearchTerm as string ) as integer
681     '///<h3>Find out how many times a string is found in a list</h3>
683     '///<u>Parameter(s):</u><br>
684     '///<ol>
686     '///+<li>List to be searched (String)</li>
687     '///<ul>
688     '///+<li>The list may not be empty</li>
689     '///+<li>Search begins at index 1</li>
690     '///</ul>
692     '///+<li>Expression to search for (String)</li>
693     '///<ul>
694     '///+<li>Only exact matches are counted</li>
695     '///</ul>
697     '///</ol>
700     '///<u>Returns:</u><br>
701     '///<ol>
702     '///+<li>Number of hits (Integer)</li>
703     '///<ul>
704     '///+<li>0: if no matches were found</li>
705     '///+<li>-1: Any error</li>
706     '///</ul>
707     '///</ol>
709     const CFN = "hCountMatchesInList::"
710     printlog( CFN & "Enter" )
711     
712     dim iHitCount as integer
713     dim iItemCount as integer
714     dim iCurrentItem as integer
716     '///<u>Description:</u>
717     '///<ul>
718     '///+<li>Retrieve the number of items in the list</li>
719     iItemCount = ListCount( acItemList() )
720     
721     '///+<li>Walk through the list and count the hits</li>
722     printlog( CFN & "Begin with term: " & cSearchTerm )
723     for iCurrentItem = 1 to iItemCount
724     
725         printlog( acItemList( iCurrentItem ) )
726     
727         if ( instr( acItemList( iCurrentItem ), cSearchTerm ) > 0 ) then
728             iHitCount = iHitCount + 1
729         endif
730         
731     next iCurrentItem
732     printlog( CFN & "End" )
733    '///</ul>
735     printlog( CFN & "Exit with result: " & iHitCount )
737     hCountMatchesInList() = iHitCount
739 end function