3 * Copyright (C) 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: subsys/system/usetup/genlist.c
22 * PURPOSE: Generic list functions
23 * PROGRAMMER: Eric Kohl
24 * Christoph von Wittich <christoph at reactos.org>
27 /* INCLUDES *****************************************************************/
34 /* FUNCTIONS ****************************************************************/
36 typedef struct _GENERIC_LIST_ENTRY
45 typedef struct _GENERIC_LIST
49 PLIST_ENTRY FirstShown
;
50 PLIST_ENTRY LastShown
;
57 PGENERIC_LIST_ENTRY CurrentEntry
;
58 PGENERIC_LIST_ENTRY BackupEntry
;
62 CreateGenericList(VOID
)
66 List
= (PGENERIC_LIST
)RtlAllocateHeap(ProcessHeap
,
68 sizeof(GENERIC_LIST
));
72 InitializeListHead(&List
->ListHead
);
80 List
->CurrentEntry
= NULL
;
91 PGENERIC_LIST_ENTRY ListEntry
;
94 /* Release list entries */
95 while (!IsListEmpty (&List
->ListHead
))
97 Entry
= RemoveHeadList (&List
->ListHead
);
98 ListEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
100 /* Release user data */
101 if (FreeUserData
&& ListEntry
->UserData
!= NULL
)
102 RtlFreeHeap (ProcessHeap
, 0, ListEntry
->UserData
);
104 /* Release list entry */
105 RtlFreeHeap (ProcessHeap
, 0, ListEntry
);
108 /* Release list head */
109 RtlFreeHeap (ProcessHeap
, 0, List
);
114 AppendGenericListEntry(
120 PGENERIC_LIST_ENTRY Entry
;
122 Entry
= (PGENERIC_LIST_ENTRY
)RtlAllocateHeap(ProcessHeap
,
124 sizeof(GENERIC_LIST_ENTRY
) + strlen(Text
));
128 strcpy (Entry
->Text
, Text
);
130 Entry
->UserData
= UserData
;
132 InsertTailList(&List
->ListHead
,
135 if (Current
|| List
->CurrentEntry
== NULL
)
137 List
->CurrentEntry
= Entry
;
147 PGENERIC_LIST GenericList
)
153 /* Draw upper left corner */
154 coPos
.X
= GenericList
->Left
;
155 coPos
.Y
= GenericList
->Top
;
156 FillConsoleOutputCharacterA (StdOutput
,
162 /* Draw upper edge */
163 coPos
.X
= GenericList
->Left
+ 1;
164 coPos
.Y
= GenericList
->Top
;
165 FillConsoleOutputCharacterA (StdOutput
,
167 GenericList
->Right
- GenericList
->Left
- 1,
171 /* Draw upper right corner */
172 coPos
.X
= GenericList
->Right
;
173 coPos
.Y
= GenericList
->Top
;
174 FillConsoleOutputCharacterA (StdOutput
,
180 /* Draw left and right edge */
181 for (i
= GenericList
->Top
+ 1; i
< GenericList
->Bottom
; i
++)
183 coPos
.X
= GenericList
->Left
;
185 FillConsoleOutputCharacterA (StdOutput
,
191 coPos
.X
= GenericList
->Right
;
192 FillConsoleOutputCharacterA (StdOutput
,
199 /* Draw lower left corner */
200 coPos
.X
= GenericList
->Left
;
201 coPos
.Y
= GenericList
->Bottom
;
202 FillConsoleOutputCharacterA (StdOutput
,
208 /* Draw lower edge */
209 coPos
.X
= GenericList
->Left
+ 1;
210 coPos
.Y
= GenericList
->Bottom
;
211 FillConsoleOutputCharacterA (StdOutput
,
213 GenericList
->Right
- GenericList
->Left
- 1,
217 /* Draw lower right corner */
218 coPos
.X
= GenericList
->Right
;
219 coPos
.Y
= GenericList
->Bottom
;
220 FillConsoleOutputCharacterA (StdOutput
,
231 PGENERIC_LIST GenericList
)
233 PGENERIC_LIST_ENTRY ListEntry
;
239 coPos
.X
= GenericList
->Left
+ 1;
240 coPos
.Y
= GenericList
->Top
+ 1;
241 Width
= GenericList
->Right
- GenericList
->Left
- 1;
243 Entry
= GenericList
->FirstShown
;
244 while (Entry
!= &GenericList
->ListHead
)
246 ListEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
248 if (coPos
.Y
== GenericList
->Bottom
)
250 GenericList
->LastShown
= Entry
;
252 FillConsoleOutputAttribute (StdOutput
,
253 (GenericList
->CurrentEntry
== ListEntry
) ?
254 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
255 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
260 FillConsoleOutputCharacterA (StdOutput
,
267 WriteConsoleOutputCharacterA (StdOutput
,
269 min (strlen(ListEntry
->Text
), (SIZE_T
)Width
- 2),
275 Entry
= Entry
->Flink
;
278 while (coPos
.Y
< GenericList
->Bottom
)
280 FillConsoleOutputAttribute (StdOutput
,
281 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
286 FillConsoleOutputCharacterA (StdOutput
,
298 DrawScrollBarGenericList(
299 PGENERIC_LIST GenericList
)
304 coPos
.X
= GenericList
->Right
+ 1;
305 coPos
.Y
= GenericList
->Top
;
307 if (GenericList
->FirstShown
!= GenericList
->ListHead
.Flink
)
309 FillConsoleOutputCharacterA (StdOutput
,
317 FillConsoleOutputCharacterA (StdOutput
,
324 coPos
.Y
= GenericList
->Bottom
;
325 if (GenericList
->LastShown
!= GenericList
->ListHead
.Blink
)
327 FillConsoleOutputCharacterA (StdOutput
,
335 FillConsoleOutputCharacterA (StdOutput
,
352 List
->FirstShown
= List
->ListHead
.Flink
;
356 List
->Bottom
= Bottom
;
360 if (IsListEmpty(&List
->ListHead
))
363 DrawListEntries(List
);
364 DrawScrollBarGenericList(List
);
369 ScrollPageDownGenericList(
374 /* Suspend auto-redraw */
375 List
->Redraw
= FALSE
;
377 for (i
= List
->Top
+ 1; i
< List
->Bottom
- 1; i
++)
379 ScrollDownGenericList (List
);
382 /* Update user interface */
383 DrawListEntries(List
);
384 DrawScrollBarGenericList(List
);
386 /* Re enable auto-redraw */
392 ScrollPageUpGenericList(
397 /* Suspend auto-redraw */
398 List
->Redraw
= FALSE
;
400 for (i
= List
->Bottom
- 1; i
> List
->Top
+ 1; i
--)
402 ScrollUpGenericList (List
);
405 /* Update user interface */
406 DrawListEntries(List
);
407 DrawScrollBarGenericList(List
);
409 /* Re enable auto-redraw */
415 ScrollDownGenericList(
420 if (List
->CurrentEntry
== NULL
)
423 if (List
->CurrentEntry
->Entry
.Flink
!= &List
->ListHead
)
425 Entry
= List
->CurrentEntry
->Entry
.Flink
;
426 if (List
->LastShown
== &List
->CurrentEntry
->Entry
)
428 List
->FirstShown
= List
->FirstShown
->Flink
;
429 List
->LastShown
= List
->LastShown
->Flink
;
431 List
->CurrentEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
435 DrawListEntries(List
);
436 DrawScrollBarGenericList(List
);
443 ScrollToPositionGenericList(
450 if (List
->CurrentEntry
== NULL
|| uIndex
== 0)
455 if (List
->CurrentEntry
->Entry
.Flink
!= &List
->ListHead
)
457 Entry
= List
->CurrentEntry
->Entry
.Flink
;
458 if (List
->LastShown
== &List
->CurrentEntry
->Entry
)
460 List
->FirstShown
= List
->FirstShown
->Flink
;
461 List
->LastShown
= List
->LastShown
->Flink
;
463 List
->CurrentEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
467 while (uIndex
!= uCount
);
471 DrawListEntries(List
);
472 DrawScrollBarGenericList(List
);
483 if (List
->CurrentEntry
== NULL
)
486 if (List
->CurrentEntry
->Entry
.Blink
!= &List
->ListHead
)
488 Entry
= List
->CurrentEntry
->Entry
.Blink
;
489 if (List
->FirstShown
== &List
->CurrentEntry
->Entry
)
491 List
->FirstShown
= List
->FirstShown
->Blink
;
492 List
->LastShown
= List
->LastShown
->Blink
;
494 List
->CurrentEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
498 DrawListEntries(List
);
499 DrawScrollBarGenericList(List
);
509 if (List
->CurrentEntry
== NULL
)
514 DrawListEntries(List
);
515 DrawScrollBarGenericList(List
);
523 PGENERIC_LIST_ENTRY Entry
)
525 if (Entry
->List
!= List
)
527 List
->CurrentEntry
= Entry
;
535 return List
->CurrentEntry
;
543 PLIST_ENTRY Entry
= List
->ListHead
.Flink
;
545 if (Entry
== &List
->ListHead
)
547 return CONTAINING_RECORD(Entry
, GENERIC_LIST_ENTRY
, Entry
);
553 PGENERIC_LIST_ENTRY Entry
)
555 PLIST_ENTRY Next
= Entry
->Entry
.Flink
;
557 if (Next
== &Entry
->List
->ListHead
)
559 return CONTAINING_RECORD(Next
, GENERIC_LIST_ENTRY
, Entry
);
564 GetListEntryUserData(
565 PGENERIC_LIST_ENTRY List
)
567 return List
->UserData
;
573 PGENERIC_LIST_ENTRY List
)
581 PGENERIC_LIST GenericList
,
584 PGENERIC_LIST_ENTRY ListEntry
;
585 PGENERIC_LIST_ENTRY OldListEntry
;
586 BOOLEAN Flag
= FALSE
;
588 ListEntry
= GenericList
->CurrentEntry
;
589 OldListEntry
= GenericList
->CurrentEntry
;
591 GenericList
->Redraw
= FALSE
;
593 if ((strlen(ListEntry
->Text
) > 0) && (tolower(ListEntry
->Text
[0]) == AsciChar
) &&
594 (GenericList
->CurrentEntry
->Entry
.Flink
!= &GenericList
->ListHead
))
596 ScrollDownGenericList(GenericList
);
597 ListEntry
= GenericList
->CurrentEntry
;
599 if ((strlen(ListEntry
->Text
) > 0) && (tolower(ListEntry
->Text
[0]) == AsciChar
))
603 while (GenericList
->CurrentEntry
->Entry
.Blink
!= &GenericList
->ListHead
)
604 ScrollUpGenericList(GenericList
);
606 ListEntry
= GenericList
->CurrentEntry
;
610 if ((strlen(ListEntry
->Text
) > 0) && (tolower(ListEntry
->Text
[0]) == AsciChar
))
616 if (GenericList
->CurrentEntry
->Entry
.Flink
== &GenericList
->ListHead
)
619 ScrollDownGenericList(GenericList
);
620 ListEntry
= GenericList
->CurrentEntry
;
625 while (GenericList
->CurrentEntry
->Entry
.Blink
!= &GenericList
->ListHead
)
627 if (GenericList
->CurrentEntry
!= OldListEntry
)
628 ScrollUpGenericList(GenericList
);
634 DrawListEntries(GenericList
);
635 DrawScrollBarGenericList(GenericList
);
637 GenericList
->Redraw
= TRUE
;
642 SaveGenericListState(
645 List
->BackupEntry
= List
->CurrentEntry
;
650 RestoreGenericListState(
653 List
->CurrentEntry
= List
->BackupEntry
;