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
;
87 DestroyGenericList(PGENERIC_LIST List
,
90 PGENERIC_LIST_ENTRY ListEntry
;
93 /* Release list entries */
94 while (!IsListEmpty (&List
->ListHead
))
96 Entry
= RemoveHeadList (&List
->ListHead
);
97 ListEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
99 /* Release user data */
100 if (FreeUserData
&& ListEntry
->UserData
!= NULL
)
101 RtlFreeHeap (ProcessHeap
, 0, ListEntry
->UserData
);
103 /* Release list entry */
104 RtlFreeHeap (ProcessHeap
, 0, ListEntry
);
107 /* Release list head */
108 RtlFreeHeap (ProcessHeap
, 0, List
);
113 AppendGenericListEntry(PGENERIC_LIST List
,
118 PGENERIC_LIST_ENTRY Entry
;
120 Entry
= (PGENERIC_LIST_ENTRY
)RtlAllocateHeap(ProcessHeap
,
122 sizeof(GENERIC_LIST_ENTRY
) + strlen(Text
));
126 strcpy (Entry
->Text
, Text
);
128 Entry
->UserData
= UserData
;
130 InsertTailList(&List
->ListHead
,
133 if (Current
|| List
->CurrentEntry
== NULL
)
135 List
->CurrentEntry
= Entry
;
143 DrawListFrame(PGENERIC_LIST GenericList
)
149 /* Draw upper left corner */
150 coPos
.X
= GenericList
->Left
;
151 coPos
.Y
= GenericList
->Top
;
152 FillConsoleOutputCharacterA (StdOutput
,
158 /* Draw upper edge */
159 coPos
.X
= GenericList
->Left
+ 1;
160 coPos
.Y
= GenericList
->Top
;
161 FillConsoleOutputCharacterA (StdOutput
,
163 GenericList
->Right
- GenericList
->Left
- 1,
167 /* Draw upper right corner */
168 coPos
.X
= GenericList
->Right
;
169 coPos
.Y
= GenericList
->Top
;
170 FillConsoleOutputCharacterA (StdOutput
,
176 /* Draw left and right edge */
177 for (i
= GenericList
->Top
+ 1; i
< GenericList
->Bottom
; i
++)
179 coPos
.X
= GenericList
->Left
;
181 FillConsoleOutputCharacterA (StdOutput
,
187 coPos
.X
= GenericList
->Right
;
188 FillConsoleOutputCharacterA (StdOutput
,
195 /* Draw lower left corner */
196 coPos
.X
= GenericList
->Left
;
197 coPos
.Y
= GenericList
->Bottom
;
198 FillConsoleOutputCharacterA (StdOutput
,
204 /* Draw lower edge */
205 coPos
.X
= GenericList
->Left
+ 1;
206 coPos
.Y
= GenericList
->Bottom
;
207 FillConsoleOutputCharacterA (StdOutput
,
209 GenericList
->Right
- GenericList
->Left
- 1,
213 /* Draw lower right corner */
214 coPos
.X
= GenericList
->Right
;
215 coPos
.Y
= GenericList
->Bottom
;
216 FillConsoleOutputCharacterA (StdOutput
,
225 DrawListEntries(PGENERIC_LIST GenericList
)
227 PGENERIC_LIST_ENTRY ListEntry
;
233 coPos
.X
= GenericList
->Left
+ 1;
234 coPos
.Y
= GenericList
->Top
+ 1;
235 Width
= GenericList
->Right
- GenericList
->Left
- 1;
237 Entry
= GenericList
->FirstShown
;
238 while (Entry
!= &GenericList
->ListHead
)
240 ListEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
242 if (coPos
.Y
== GenericList
->Bottom
)
244 GenericList
->LastShown
= Entry
;
246 FillConsoleOutputAttribute (StdOutput
,
247 (GenericList
->CurrentEntry
== ListEntry
) ?
248 FOREGROUND_BLUE
| BACKGROUND_WHITE
:
249 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
254 FillConsoleOutputCharacterA (StdOutput
,
261 WriteConsoleOutputCharacterA (StdOutput
,
263 min (strlen(ListEntry
->Text
), (SIZE_T
)Width
- 2),
269 Entry
= Entry
->Flink
;
272 while (coPos
.Y
< GenericList
->Bottom
)
274 FillConsoleOutputAttribute (StdOutput
,
275 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
280 FillConsoleOutputCharacterA (StdOutput
,
290 DrawScrollBarGenericList(PGENERIC_LIST GenericList
)
295 coPos
.X
= GenericList
->Right
+ 1;
296 coPos
.Y
= GenericList
->Top
;
298 if (GenericList
->FirstShown
!= GenericList
->ListHead
.Flink
)
300 FillConsoleOutputCharacterA (StdOutput
,
308 FillConsoleOutputCharacterA (StdOutput
,
315 coPos
.Y
= GenericList
->Bottom
;
316 if (GenericList
->LastShown
!= GenericList
->ListHead
.Blink
)
318 FillConsoleOutputCharacterA (StdOutput
,
326 FillConsoleOutputCharacterA (StdOutput
,
335 DrawGenericList(PGENERIC_LIST List
,
341 List
->FirstShown
= List
->ListHead
.Flink
;
345 List
->Bottom
= Bottom
;
349 if (IsListEmpty(&List
->ListHead
))
352 DrawListEntries(List
);
353 DrawScrollBarGenericList(List
);
357 ScrollPageDownGenericList (PGENERIC_LIST List
)
361 /* Suspend auto-redraw */
362 List
->Redraw
= FALSE
;
364 for (i
= List
->Top
+ 1; i
< List
->Bottom
- 1; i
++)
366 ScrollDownGenericList (List
);
369 /* Update user interface */
370 DrawListEntries(List
);
371 DrawScrollBarGenericList(List
);
373 /* Re enable auto-redraw */
378 ScrollPageUpGenericList (PGENERIC_LIST List
)
382 /* Suspend auto-redraw */
383 List
->Redraw
= FALSE
;
385 for (i
= List
->Bottom
- 1; i
> List
->Top
+ 1; i
--)
387 ScrollUpGenericList (List
);
390 /* Update user interface */
391 DrawListEntries(List
);
392 DrawScrollBarGenericList(List
);
394 /* Re enable auto-redraw */
399 ScrollDownGenericList (PGENERIC_LIST List
)
403 if (List
->CurrentEntry
== NULL
)
406 if (List
->CurrentEntry
->Entry
.Flink
!= &List
->ListHead
)
408 Entry
= List
->CurrentEntry
->Entry
.Flink
;
409 if (List
->LastShown
== &List
->CurrentEntry
->Entry
)
411 List
->FirstShown
= List
->FirstShown
->Flink
;
412 List
->LastShown
= List
->LastShown
->Flink
;
414 List
->CurrentEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
418 DrawListEntries(List
);
419 DrawScrollBarGenericList(List
);
426 ScrollToPositionGenericList (PGENERIC_LIST List
, ULONG uIndex
)
431 if (List
->CurrentEntry
== NULL
)
436 if (List
->CurrentEntry
->Entry
.Flink
!= &List
->ListHead
)
438 Entry
= List
->CurrentEntry
->Entry
.Flink
;
439 if (List
->LastShown
== &List
->CurrentEntry
->Entry
)
441 List
->FirstShown
= List
->FirstShown
->Flink
;
442 List
->LastShown
= List
->LastShown
->Flink
;
444 List
->CurrentEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
448 while (uIndex
!= uCount
);
452 DrawListEntries(List
);
453 DrawScrollBarGenericList(List
);
459 ScrollUpGenericList (PGENERIC_LIST List
)
463 if (List
->CurrentEntry
== NULL
)
466 if (List
->CurrentEntry
->Entry
.Blink
!= &List
->ListHead
)
468 Entry
= List
->CurrentEntry
->Entry
.Blink
;
469 if (List
->FirstShown
== &List
->CurrentEntry
->Entry
)
471 List
->FirstShown
= List
->FirstShown
->Blink
;
472 List
->LastShown
= List
->LastShown
->Blink
;
474 List
->CurrentEntry
= CONTAINING_RECORD (Entry
, GENERIC_LIST_ENTRY
, Entry
);
478 DrawListEntries(List
);
479 DrawScrollBarGenericList(List
);
486 SetCurrentListEntry(PGENERIC_LIST List
, PGENERIC_LIST_ENTRY Entry
)
488 if (Entry
->List
!= List
)
490 List
->CurrentEntry
= Entry
;
495 GetCurrentListEntry(PGENERIC_LIST List
)
497 return List
->CurrentEntry
;
502 GetFirstListEntry(PGENERIC_LIST List
)
504 PLIST_ENTRY Entry
= List
->ListHead
.Flink
;
506 if (Entry
== &List
->ListHead
)
508 return CONTAINING_RECORD(Entry
, GENERIC_LIST_ENTRY
, Entry
);
513 GetNextListEntry(PGENERIC_LIST_ENTRY Entry
)
515 PLIST_ENTRY Next
= Entry
->Entry
.Flink
;
517 if (Next
== &Entry
->List
->ListHead
)
519 return CONTAINING_RECORD(Next
, GENERIC_LIST_ENTRY
, Entry
);
524 GetListEntryUserData(PGENERIC_LIST_ENTRY List
)
526 return List
->UserData
;
531 GetListEntryText(PGENERIC_LIST_ENTRY List
)
538 GenericListKeyPress (PGENERIC_LIST GenericList
, CHAR AsciChar
)
540 PGENERIC_LIST_ENTRY ListEntry
;
541 PGENERIC_LIST_ENTRY OldListEntry
;
542 BOOLEAN Flag
= FALSE
;
544 ListEntry
= GenericList
->CurrentEntry
;
545 OldListEntry
= GenericList
->CurrentEntry
;
547 GenericList
->Redraw
= FALSE
;
549 if ((strlen(ListEntry
->Text
) > 0) && (tolower(ListEntry
->Text
[0]) == AsciChar
) &&
550 (GenericList
->CurrentEntry
->Entry
.Flink
!= &GenericList
->ListHead
))
552 ScrollDownGenericList(GenericList
);
553 ListEntry
= GenericList
->CurrentEntry
;
555 if ((strlen(ListEntry
->Text
) > 0) && (tolower(ListEntry
->Text
[0]) == AsciChar
))
559 while (GenericList
->CurrentEntry
->Entry
.Blink
!= &GenericList
->ListHead
)
560 ScrollUpGenericList(GenericList
);
562 ListEntry
= GenericList
->CurrentEntry
;
566 if ((strlen(ListEntry
->Text
) > 0) && (tolower(ListEntry
->Text
[0]) == AsciChar
))
572 if (GenericList
->CurrentEntry
->Entry
.Flink
== &GenericList
->ListHead
)
575 ScrollDownGenericList(GenericList
);
576 ListEntry
= GenericList
->CurrentEntry
;
581 while (GenericList
->CurrentEntry
->Entry
.Blink
!= &GenericList
->ListHead
)
583 if (GenericList
->CurrentEntry
!= OldListEntry
)
584 ScrollUpGenericList(GenericList
);
590 DrawListEntries(GenericList
);
591 DrawScrollBarGenericList(GenericList
);
593 GenericList
->Redraw
= TRUE
;
598 SaveGenericListState(PGENERIC_LIST List
)
600 List
->BackupEntry
= List
->CurrentEntry
;
605 RestoreGenericListState(PGENERIC_LIST List
)
607 List
->CurrentEntry
= List
->BackupEntry
;