[SETUPLIB][USETUP] Remove the deprecated GenericListHasSingleEntry() function and...
[reactos.git] / base / setup / usetup / genlist.c
index 6e5a736..c43f89c 100644 (file)
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
-/* COPYRIGHT:       See COPYING in the top level directory
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS text-mode setup
- * FILE:            subsys/system/usetup/genlist.c
+ * FILE:            base/setup/usetup/genlist.c
  * PURPOSE:         Generic list functions
- * PROGRAMMER:      Eric Kohl
- *                  Christoph von Wittich <christoph at reactos.org>
+ * PROGRAMMER:      Christoph von Wittich <christoph at reactos.org>
  */
 
 /* INCLUDES *****************************************************************/
 
 /* FUNCTIONS ****************************************************************/
 
-typedef struct _GENERIC_LIST_ENTRY
-{
-    LIST_ENTRY Entry;
-    PGENERIC_LIST List;
-    PVOID UserData;
-    CHAR Text[1];
-} GENERIC_LIST_ENTRY;
-
-
-typedef struct _GENERIC_LIST
-{
-    LIST_ENTRY ListHead;
-
-    PLIST_ENTRY FirstShown;
-    PLIST_ENTRY LastShown;
-    SHORT Left;
-    SHORT Top;
-    SHORT Right;
-    SHORT Bottom;
-    BOOL Redraw;
-
-    PGENERIC_LIST_ENTRY CurrentEntry;
-    PGENERIC_LIST_ENTRY BackupEntry;
-} GENERIC_LIST;
-
-PGENERIC_LIST
-CreateGenericList(VOID)
-{
-    PGENERIC_LIST List;
-
-    List = (PGENERIC_LIST)RtlAllocateHeap(ProcessHeap,
-                                          0,
-                                          sizeof(GENERIC_LIST));
-    if (List == NULL)
-        return NULL;
-
-    InitializeListHead(&List->ListHead);
-
-    List->Left = 0;
-    List->Top = 0;
-    List->Right = 0;
-    List->Bottom = 0;
-    List->Redraw = TRUE;
-
-    List->CurrentEntry = NULL;
-
-    return List;
-}
-
-
 VOID
-DestroyGenericList(
-    PGENERIC_LIST List,
-    BOOLEAN FreeUserData)
+InitGenericListUi(
+    IN OUT PGENERIC_LIST_UI ListUi,
+    IN PGENERIC_LIST List,
+    IN PGET_ENTRY_DESCRIPTION GetEntryDescriptionProc)
 {
-    PGENERIC_LIST_ENTRY ListEntry;
-    PLIST_ENTRY Entry;
+    ListUi->List = List;
+    ListUi->FirstShown = NULL;
+    ListUi->LastShown = NULL;
+    ListUi->BackupEntry = NULL;
 
-    /* Release list entries */
-    while (!IsListEmpty (&List->ListHead))
-    {
-        Entry = RemoveHeadList (&List->ListHead);
-        ListEntry = CONTAINING_RECORD (Entry, GENERIC_LIST_ENTRY, Entry);
+    ListUi->GetEntryDescriptionProc = GetEntryDescriptionProc;
 
-        /* Release user data */
-        if (FreeUserData && ListEntry->UserData != NULL)
-            RtlFreeHeap (ProcessHeap, 0, ListEntry->UserData);
+    ListUi->Left = 0;
+    ListUi->Top = 0;
+    ListUi->Right = 0;
+    ListUi->Bottom = 0;
+    ListUi->Redraw = TRUE;
 
-        /* Release list entry */
-        RtlFreeHeap (ProcessHeap, 0, ListEntry);
-    }
+    ListUi->CurrentItemText[0] = ANSI_NULL;
 
-    /* Release list head */
-    RtlFreeHeap (ProcessHeap, 0, List);
+    /* SaveGenericListUiState(ListUi); */
+    ListUi->BackupEntry = ListUi->List->CurrentEntry;
 }
 
-
-BOOLEAN
-AppendGenericListEntry(
-    PGENERIC_LIST List,
-    PCHAR Text,
-    PVOID UserData,
-    BOOLEAN Current)
+VOID
+RestoreGenericListUiState(
+    IN PGENERIC_LIST_UI ListUi)
 {
-    PGENERIC_LIST_ENTRY Entry;
-
-    Entry = (PGENERIC_LIST_ENTRY)RtlAllocateHeap(ProcessHeap,
-                                                 0,
-                                                 sizeof(GENERIC_LIST_ENTRY) + strlen(Text));
-    if (Entry == NULL)
-        return FALSE;
-
-    strcpy (Entry->Text, Text);
-    Entry->List = List;
-    Entry->UserData = UserData;
-
-    InsertTailList(&List->ListHead,
-                   &Entry->Entry);
-
-    if (Current || List->CurrentEntry == NULL)
-    {
-        List->CurrentEntry = Entry;
-    }
-
-    return TRUE;
+    ListUi->List->CurrentEntry = ListUi->BackupEntry;
 }
 
-
 static
 VOID
 DrawListFrame(
-    PGENERIC_LIST GenericList)
+    IN PGENERIC_LIST_UI ListUi)
 {
     COORD coPos;
     DWORD Written;
     SHORT i;
 
     /* Draw upper left corner */
-    coPos.X = GenericList->Left;
-    coPos.Y = GenericList->Top;
-    FillConsoleOutputCharacterA (StdOutput,
-                                 0xDA, // '+',
-                                 1,
-                                 coPos,
-                                 &Written);
+    coPos.X = ListUi->Left;
+    coPos.Y = ListUi->Top;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xDA, // '+',
+                                1,
+                                coPos,
+                                &Written);
 
     /* Draw upper edge */
-    coPos.X = GenericList->Left + 1;
-    coPos.Y = GenericList->Top;
-    FillConsoleOutputCharacterA (StdOutput,
-                                 0xC4, // '-',
-                                 GenericList->Right - GenericList->Left - 1,
-                                 coPos,
-                                 &Written);
+    coPos.X = ListUi->Left + 1;
+    coPos.Y = ListUi->Top;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xC4, // '-',
+                                ListUi->Right - ListUi->Left - 1,
+                                coPos,
+                                &Written);
 
     /* Draw upper right corner */
-    coPos.X = GenericList->Right;
-    coPos.Y = GenericList->Top;
-    FillConsoleOutputCharacterA (StdOutput,
-                                 0xBF, // '+',
-                                 1,
-                                 coPos,
-                                 &Written);
+    coPos.X = ListUi->Right;
+    coPos.Y = ListUi->Top;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xBF, // '+',
+                                1,
+                                coPos,
+                                &Written);
 
     /* Draw left and right edge */
-    for (i = GenericList->Top + 1; i < GenericList->Bottom; i++)
+    for (i = ListUi->Top + 1; i < ListUi->Bottom; i++)
     {
-        coPos.X = GenericList->Left;
+        coPos.X = ListUi->Left;
         coPos.Y = i;
-        FillConsoleOutputCharacterA (StdOutput,
-                                     0xB3, // '|',
-                                     1,
-                                     coPos,
-                                     &Written);
+        FillConsoleOutputCharacterA(StdOutput,
+                                    0xB3, // '|',
+                                    1,
+                                    coPos,
+                                    &Written);
 
-        coPos.X = GenericList->Right;
-        FillConsoleOutputCharacterA (StdOutput,
-                                     0xB3, //'|',
-                                     1,
-                                     coPos,
-                                     &Written);
+        coPos.X = ListUi->Right;
+        FillConsoleOutputCharacterA(StdOutput,
+                                    0xB3, //'|',
+                                    1,
+                                    coPos,
+                                    &Written);
     }
 
     /* Draw lower left corner */
-    coPos.X = GenericList->Left;
-    coPos.Y = GenericList->Bottom;
-    FillConsoleOutputCharacterA (StdOutput,
-                                 0xC0, // '+',
-                                 1,
-                                 coPos,
-                                 &Written);
+    coPos.X = ListUi->Left;
+    coPos.Y = ListUi->Bottom;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xC0, // '+',
+                                1,
+                                coPos,
+                                &Written);
 
     /* Draw lower edge */
-    coPos.X = GenericList->Left + 1;
-    coPos.Y = GenericList->Bottom;
-    FillConsoleOutputCharacterA (StdOutput,
-                                 0xC4, // '-',
-                                 GenericList->Right - GenericList->Left - 1,
-                                 coPos,
-                                 &Written);
+    coPos.X = ListUi->Left + 1;
+    coPos.Y = ListUi->Bottom;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xC4, // '-',
+                                ListUi->Right - ListUi->Left - 1,
+                                coPos,
+                                &Written);
 
     /* Draw lower right corner */
-    coPos.X = GenericList->Right;
-    coPos.Y = GenericList->Bottom;
-    FillConsoleOutputCharacterA (StdOutput,
-                                 0xD9, // '+',
-                                 1,
-                                 coPos,
-                                 &Written);
+    coPos.X = ListUi->Right;
+    coPos.Y = ListUi->Bottom;
+    FillConsoleOutputCharacterA(StdOutput,
+                                0xD9, // '+',
+                                1,
+                                coPos,
+                                &Written);
 }
 
-
 static
 VOID
 DrawListEntries(
-    PGENERIC_LIST GenericList)
+    IN PGENERIC_LIST_UI ListUi)
 {
+    PGENERIC_LIST List = ListUi->List;
     PGENERIC_LIST_ENTRY ListEntry;
     PLIST_ENTRY Entry;
     COORD coPos;
     DWORD Written;
     USHORT Width;
 
-    coPos.X = GenericList->Left + 1;
-    coPos.Y = GenericList->Top + 1;
-    Width = GenericList->Right - GenericList->Left - 1;
+    coPos.X = ListUi->Left + 1;
+    coPos.Y = ListUi->Top + 1;
+    Width = ListUi->Right - ListUi->Left - 1;
 
-    Entry = GenericList->FirstShown;
-    while (Entry != &GenericList->ListHead)
+    Entry = ListUi->FirstShown;
+    while (Entry != &List->ListHead)
     {
-        ListEntry = CONTAINING_RECORD (Entry, GENERIC_LIST_ENTRY, Entry);
+        ListEntry = CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
 
-        if (coPos.Y == GenericList->Bottom)
+        if (coPos.Y == ListUi->Bottom)
             break;
-        GenericList->LastShown = Entry;
+        ListUi->LastShown = Entry;
+
+        ListUi->CurrentItemText[0] = ANSI_NULL;
+        if (ListUi->GetEntryDescriptionProc)
+        {
+            ListUi->GetEntryDescriptionProc(ListEntry,
+                                            ListUi->CurrentItemText,
+                                            ARRAYSIZE(ListUi->CurrentItemText));
+        }
+
+        FillConsoleOutputAttribute(StdOutput,
+                                   (List->CurrentEntry == ListEntry) ?
+                                   FOREGROUND_BLUE | BACKGROUND_WHITE :
+                                   FOREGROUND_WHITE | BACKGROUND_BLUE,
+                                   Width,
+                                   coPos,
+                                   &Written);
 
-        FillConsoleOutputAttribute (StdOutput,
-                                    (GenericList->CurrentEntry == ListEntry) ?
-                                    FOREGROUND_BLUE | BACKGROUND_WHITE :
-                                    FOREGROUND_WHITE | BACKGROUND_BLUE,
+        FillConsoleOutputCharacterA(StdOutput,
+                                    ' ',
                                     Width,
                                     coPos,
                                     &Written);
 
-        FillConsoleOutputCharacterA (StdOutput,
-                                     ' ',
-                                     Width,
+        coPos.X++;
+        WriteConsoleOutputCharacterA(StdOutput,
+                                     ListUi->CurrentItemText,
+                                     min(strlen(ListUi->CurrentItemText), (SIZE_T)Width - 2),
                                      coPos,
                                      &Written);
-
-        coPos.X++;
-        WriteConsoleOutputCharacterA (StdOutput,
-                                      ListEntry->Text,
-                                      min (strlen(ListEntry->Text), (SIZE_T)Width - 2),
-                                      coPos,
-                                      &Written);
         coPos.X--;
 
         coPos.Y++;
         Entry = Entry->Flink;
     }
 
-    while (coPos.Y < GenericList->Bottom)
+    while (coPos.Y < ListUi->Bottom)
     {
-        FillConsoleOutputAttribute (StdOutput,
-                                    FOREGROUND_WHITE | BACKGROUND_BLUE,
+        FillConsoleOutputAttribute(StdOutput,
+                                   FOREGROUND_WHITE | BACKGROUND_BLUE,
+                                   Width,
+                                   coPos,
+                                   &Written);
+
+        FillConsoleOutputCharacterA(StdOutput,
+                                    ' ',
                                     Width,
                                     coPos,
                                     &Written);
-
-        FillConsoleOutputCharacterA (StdOutput,
-                                     ' ',
-                                     Width,
-                                     coPos,
-                                     &Written);
         coPos.Y++;
     }
 }
 
-
 static
 VOID
 DrawScrollBarGenericList(
-    PGENERIC_LIST GenericList)
+    IN PGENERIC_LIST_UI ListUi)
 {
+    PGENERIC_LIST List = ListUi->List;
     COORD coPos;
     DWORD Written;
 
-    coPos.X = GenericList->Right + 1;
-    coPos.Y = GenericList->Top;
+    coPos.X = ListUi->Right + 1;
+    coPos.Y = ListUi->Top;
 
-    if (GenericList->FirstShown != GenericList->ListHead.Flink)
+    if (ListUi->FirstShown != List->ListHead.Flink)
     {
-        FillConsoleOutputCharacterA (StdOutput,
-                                     '\x18',
-                                     1,
-                                     coPos,
-                                     &Written);
+        FillConsoleOutputCharacterA(StdOutput,
+                                    '\x18',
+                                    1,
+                                    coPos,
+                                    &Written);
     }
     else
     {
-        FillConsoleOutputCharacterA (StdOutput,
-                                     ' ',
-                                     1,
-                                     coPos,
-                                     &Written);
+        FillConsoleOutputCharacterA(StdOutput,
+                                    ' ',
+                                    1,
+                                    coPos,
+                                    &Written);
     }
 
-    coPos.Y = GenericList->Bottom;
-    if (GenericList->LastShown != GenericList->ListHead.Blink)
+    coPos.Y = ListUi->Bottom;
+    if (ListUi->LastShown != List->ListHead.Blink)
     {
-        FillConsoleOutputCharacterA (StdOutput,
-                                     '\x19',
-                                     1,
-                                     coPos,
-                                     &Written);
+        FillConsoleOutputCharacterA(StdOutput,
+                                    '\x19',
+                                    1,
+                                    coPos,
+                                    &Written);
     }
     else
     {
-        FillConsoleOutputCharacterA (StdOutput,
-                                     ' ',
-                                     1,
-                                     coPos,
-                                     &Written);
+        FillConsoleOutputCharacterA(StdOutput,
+                                    ' ',
+                                    1,
+                                    coPos,
+                                    &Written);
     }
 }
 
-
+static
 VOID
-DrawGenericList(
-    PGENERIC_LIST List,
-    SHORT Left,
-    SHORT Top,
-    SHORT Right,
-    SHORT Bottom)
+CenterCurrentListItem(
+    IN PGENERIC_LIST_UI ListUi)
 {
-    List->FirstShown = List->ListHead.Flink;
-    List->Left = Left;
-    List->Top = Top;
-    List->Right = Right;
-    List->Bottom = Bottom;
-
-    DrawListFrame(List);
+    PGENERIC_LIST List = ListUi->List;
+    PLIST_ENTRY Entry;
+    ULONG MaxVisibleItems, ItemCount, i;
 
-    if (IsListEmpty(&List->ListHead))
+    if ((ListUi->Top == 0 && ListUi->Bottom == 0) ||
+        IsListEmpty(&List->ListHead) ||
+        List->CurrentEntry == NULL)
+    {
         return;
+    }
 
-    DrawListEntries(List);
-    DrawScrollBarGenericList(List);
-}
+    MaxVisibleItems = (ULONG)(ListUi->Bottom - ListUi->Top - 1);
+
+/*****************************************
+    ItemCount = 0;
+    Entry = List->ListHead.Flink;
+    while (Entry != &List->ListHead)
+    {
+        ItemCount++;
+        Entry = Entry->Flink;
+    }
+*****************************************/
+    ItemCount = List->NumOfEntries; // GetNumberOfListEntries(List);
+
+    if (ItemCount > MaxVisibleItems)
+    {
+        Entry = &List->CurrentEntry->Entry;
+        for (i = 0; i < MaxVisibleItems / 2; i++)
+        {
+            if (Entry->Blink != &List->ListHead)
+                Entry = Entry->Blink;
+        }
 
+        ListUi->FirstShown = Entry;
+
+        for (i = 0; i < MaxVisibleItems; i++)
+        {
+            if (Entry->Flink != &List->ListHead)
+                Entry = Entry->Flink;
+        }
+
+        ListUi->LastShown = Entry;
+    }
+}
 
 VOID
-ScrollPageDownGenericList(
-    PGENERIC_LIST List)
+DrawGenericList(
+    IN PGENERIC_LIST_UI ListUi,
+    IN SHORT Left,
+    IN SHORT Top,
+    IN SHORT Right,
+    IN SHORT Bottom)
 {
-    SHORT i;
+    PGENERIC_LIST List = ListUi->List;
 
-    /* Suspend auto-redraw */
-    List->Redraw = FALSE;
+    ListUi->FirstShown = List->ListHead.Flink;
+    ListUi->Left = Left;
+    ListUi->Top = Top;
+    ListUi->Right = Right;
+    ListUi->Bottom = Bottom;
 
-    for (i = List->Top + 1; i < List->Bottom - 1; i++)
-    {
-        ScrollDownGenericList (List);
-    }
+    DrawListFrame(ListUi);
 
-    /* Update user interface */
-    DrawListEntries(List);
-    DrawScrollBarGenericList(List);
+    if (IsListEmpty(&List->ListHead))
+        return;
 
-    /* Re enable auto-redraw */
-    List->Redraw = TRUE;
-}
+    CenterCurrentListItem(ListUi);
 
+    DrawListEntries(ListUi);
+    DrawScrollBarGenericList(ListUi);
+}
 
 VOID
-ScrollPageUpGenericList(
-    PGENERIC_LIST List)
+DrawGenericListCurrentItem(
+    IN PGENERIC_LIST List,
+    IN PGET_ENTRY_DESCRIPTION GetEntryDescriptionProc,
+    IN SHORT Left,
+    IN SHORT Top)
 {
-    SHORT i;
+    CHAR CurrentItemText[256];
 
-    /* Suspend auto-redraw */
-    List->Redraw = FALSE;
-
-    for (i = List->Bottom - 1; i > List->Top + 1; i--)
+    if (GetEntryDescriptionProc &&
+        GetNumberOfListEntries(List) > 0)
     {
-         ScrollUpGenericList (List);
+        GetEntryDescriptionProc(GetCurrentListEntry(List),
+                                CurrentItemText,
+                                ARRAYSIZE(CurrentItemText));
+        CONSOLE_SetTextXY(Left, Top, CurrentItemText);
+    }
+    else
+    {
+        CONSOLE_SetTextXY(Left, Top, "");
     }
-
-    /* Update user interface */
-    DrawListEntries(List);
-    DrawScrollBarGenericList(List);
-
-    /* Re enable auto-redraw */
-    List->Redraw = TRUE;
 }
 
-
 VOID
 ScrollDownGenericList(
-    PGENERIC_LIST List)
+    IN PGENERIC_LIST_UI ListUi)
 {
+    PGENERIC_LIST List = ListUi->List;
     PLIST_ENTRY Entry;
 
     if (List->CurrentEntry == NULL)
@@ -423,61 +385,26 @@ ScrollDownGenericList(
     if (List->CurrentEntry->Entry.Flink != &List->ListHead)
     {
         Entry = List->CurrentEntry->Entry.Flink;
-        if (List->LastShown == &List->CurrentEntry->Entry)
+        if (ListUi->LastShown == &List->CurrentEntry->Entry)
         {
-            List->FirstShown = List->FirstShown->Flink;
-            List->LastShown = List->LastShown->Flink;
+            ListUi->FirstShown = ListUi->FirstShown->Flink;
+            ListUi->LastShown = ListUi->LastShown->Flink;
         }
-        List->CurrentEntry = CONTAINING_RECORD (Entry, GENERIC_LIST_ENTRY, Entry);
+        List->CurrentEntry = CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
 
-        if (List->Redraw)
+        if (ListUi->Redraw)
         {
-            DrawListEntries(List);
-            DrawScrollBarGenericList(List);
+            DrawListEntries(ListUi);
+            DrawScrollBarGenericList(ListUi);
         }
     }
 }
 
-
-VOID
-ScrollToPositionGenericList(
-    PGENERIC_LIST List,
-    ULONG uIndex)
-{
-    PLIST_ENTRY Entry;
-    ULONG uCount = 0;
-
-    if (List->CurrentEntry == NULL || uIndex == 0)
-        return;
-
-    do
-    {
-        if (List->CurrentEntry->Entry.Flink != &List->ListHead)
-        {
-            Entry = List->CurrentEntry->Entry.Flink;
-            if (List->LastShown == &List->CurrentEntry->Entry)
-            {
-                List->FirstShown = List->FirstShown->Flink;
-                List->LastShown = List->LastShown->Flink;
-            }
-            List->CurrentEntry = CONTAINING_RECORD (Entry, GENERIC_LIST_ENTRY, Entry);
-        }
-        uCount++;
-    }
-    while (uIndex != uCount);
-
-    if (List->Redraw)
-    {
-        DrawListEntries(List);
-        DrawScrollBarGenericList(List);
-    }
-}
-
-
 VOID
 ScrollUpGenericList(
-    PGENERIC_LIST List)
+    IN PGENERIC_LIST_UI ListUi)
 {
+    PGENERIC_LIST List = ListUi->List;
     PLIST_ENTRY Entry;
 
     if (List->CurrentEntry == NULL)
@@ -486,171 +413,199 @@ ScrollUpGenericList(
     if (List->CurrentEntry->Entry.Blink != &List->ListHead)
     {
         Entry = List->CurrentEntry->Entry.Blink;
-        if (List->FirstShown == &List->CurrentEntry->Entry)
+        if (ListUi->FirstShown == &List->CurrentEntry->Entry)
         {
-            List->FirstShown = List->FirstShown->Blink;
-            List->LastShown = List->LastShown->Blink;
+            ListUi->FirstShown = ListUi->FirstShown->Blink;
+            ListUi->LastShown = ListUi->LastShown->Blink;
         }
-        List->CurrentEntry = CONTAINING_RECORD (Entry, GENERIC_LIST_ENTRY, Entry);
+        List->CurrentEntry = CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
 
-        if (List->Redraw)
+        if (ListUi->Redraw)
         {
-            DrawListEntries(List);
-            DrawScrollBarGenericList(List);
+            DrawListEntries(ListUi);
+            DrawScrollBarGenericList(ListUi);
         }
     }
 }
 
-
 VOID
-RedrawGenericList(
-    PGENERIC_LIST List)
+ScrollPageDownGenericList(
+    IN PGENERIC_LIST_UI ListUi)
 {
-    if (List->CurrentEntry == NULL)
-        return;
+    SHORT i;
 
-    if (List->Redraw)
+    /* Suspend auto-redraw */
+    ListUi->Redraw = FALSE;
+
+    for (i = ListUi->Top + 1; i < ListUi->Bottom - 1; i++)
     {
-        DrawListEntries(List);
-        DrawScrollBarGenericList(List);
+        ScrollDownGenericList(ListUi);
     }
-}
 
+    /* Update user interface */
+    DrawListEntries(ListUi);
+    DrawScrollBarGenericList(ListUi);
 
-VOID
-SetCurrentListEntry(
-    PGENERIC_LIST List,
-    PGENERIC_LIST_ENTRY Entry)
-{
-    if (Entry->List != List)
-        return;
-    List->CurrentEntry = Entry;
+    /* Re enable auto-redraw */
+    ListUi->Redraw = TRUE;
 }
 
-
-PGENERIC_LIST_ENTRY
-GetCurrentListEntry(
-    PGENERIC_LIST List)
+VOID
+ScrollPageUpGenericList(
+    IN PGENERIC_LIST_UI ListUi)
 {
-    return List->CurrentEntry;
-}
+    SHORT i;
 
+    /* Suspend auto-redraw */
+    ListUi->Redraw = FALSE;
 
-PGENERIC_LIST_ENTRY
-GetFirstListEntry(
-    PGENERIC_LIST List)
-{
-    PLIST_ENTRY Entry = List->ListHead.Flink;
+    for (i = ListUi->Bottom - 1; i > ListUi->Top + 1; i--)
+    {
+        ScrollUpGenericList(ListUi);
+    }
 
-    if (Entry == &List->ListHead)
-        return NULL;
-    return CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
-}
+    /* Update user interface */
+    DrawListEntries(ListUi);
+    DrawScrollBarGenericList(ListUi);
 
+    /* Re enable auto-redraw */
+    ListUi->Redraw = TRUE;
+}
 
-PGENERIC_LIST_ENTRY
-GetNextListEntry(
-    PGENERIC_LIST_ENTRY Entry)
+VOID
+ScrollToPositionGenericList(
+    IN PGENERIC_LIST_UI ListUi,
+    IN ULONG uIndex)
 {
-    PLIST_ENTRY Next = Entry->Entry.Flink;
+    PGENERIC_LIST List = ListUi->List;
+    PLIST_ENTRY Entry;
+    ULONG uCount = 0;
 
-    if (Next == &Entry->List->ListHead)
-        return NULL;
-    return CONTAINING_RECORD(Next, GENERIC_LIST_ENTRY, Entry);
-}
+    if (List->CurrentEntry == NULL || uIndex == 0)
+        return;
 
+    do
+    {
+        if (List->CurrentEntry->Entry.Flink != &List->ListHead)
+        {
+            Entry = List->CurrentEntry->Entry.Flink;
+            if (ListUi->LastShown == &List->CurrentEntry->Entry)
+            {
+                ListUi->FirstShown = ListUi->FirstShown->Flink;
+                ListUi->LastShown = ListUi->LastShown->Flink;
+            }
+            List->CurrentEntry = CONTAINING_RECORD(Entry, GENERIC_LIST_ENTRY, Entry);
+        }
+        uCount++;
+    }
+    while (uIndex != uCount);
 
-PVOID
-GetListEntryUserData(
-    PGENERIC_LIST_ENTRY List)
-{
-    return List->UserData;
+    if (ListUi->Redraw)
+    {
+        DrawListEntries(ListUi);
+        DrawScrollBarGenericList(ListUi);
+    }
 }
 
-
-LPCSTR
-GetListEntryText(
-    PGENERIC_LIST_ENTRY List)
+VOID
+RedrawGenericList(
+    IN PGENERIC_LIST_UI ListUi)
 {
-    return List->Text;
-}
+    if (ListUi->List->CurrentEntry == NULL)
+        return;
 
+    if (ListUi->Redraw)
+    {
+        DrawListEntries(ListUi);
+        DrawScrollBarGenericList(ListUi);
+    }
+}
 
 VOID
 GenericListKeyPress(
-    PGENERIC_LIST GenericList,
-    CHAR AsciChar)
+    IN PGENERIC_LIST_UI ListUi,
+    IN CHAR AsciiChar)
 {
+    PGENERIC_LIST List = ListUi->List;
     PGENERIC_LIST_ENTRY ListEntry;
     PGENERIC_LIST_ENTRY OldListEntry;
     BOOLEAN Flag = FALSE;
 
-    ListEntry = GenericList->CurrentEntry;
-    OldListEntry = GenericList->CurrentEntry;
+    ListEntry = List->CurrentEntry;
+    OldListEntry = List->CurrentEntry;
 
-    GenericList->Redraw = FALSE;
+    ListUi->Redraw = FALSE;
 
-    if ((strlen(ListEntry->Text) > 0) && (tolower(ListEntry->Text[0]) == AsciChar) &&
-         (GenericList->CurrentEntry->Entry.Flink != &GenericList->ListHead))
+    ListUi->CurrentItemText[0] = ANSI_NULL;
+    if (ListUi->GetEntryDescriptionProc)
     {
-        ScrollDownGenericList(GenericList);
-        ListEntry = GenericList->CurrentEntry;
+        ListUi->GetEntryDescriptionProc(ListEntry,
+                                        ListUi->CurrentItemText,
+                                        ARRAYSIZE(ListUi->CurrentItemText));
+    }
 
-        if ((strlen(ListEntry->Text) > 0) && (tolower(ListEntry->Text[0]) == AsciChar))
+    if ((strlen(ListUi->CurrentItemText) > 0) && (tolower(ListUi->CurrentItemText[0]) == AsciiChar) &&
+         (List->CurrentEntry->Entry.Flink != &List->ListHead))
+    {
+        ScrollDownGenericList(ListUi);
+        ListEntry = List->CurrentEntry;
+
+        ListUi->CurrentItemText[0] = ANSI_NULL;
+        if (ListUi->GetEntryDescriptionProc)
+        {
+            ListUi->GetEntryDescriptionProc(ListEntry,
+                                            ListUi->CurrentItemText,
+                                            ARRAYSIZE(ListUi->CurrentItemText));
+        }
+
+        if ((strlen(ListUi->CurrentItemText) > 0) && (tolower(ListUi->CurrentItemText[0]) == AsciiChar))
             goto End;
     }
 
-    while (GenericList->CurrentEntry->Entry.Blink != &GenericList->ListHead)
-        ScrollUpGenericList(GenericList);
+    while (List->CurrentEntry->Entry.Blink != &List->ListHead)
+        ScrollUpGenericList(ListUi);
 
-    ListEntry = GenericList->CurrentEntry;
+    ListEntry = List->CurrentEntry;
 
     for (;;)
     {
-        if ((strlen(ListEntry->Text) > 0) && (tolower(ListEntry->Text[0]) == AsciChar))
+        ListUi->CurrentItemText[0] = ANSI_NULL;
+        if (ListUi->GetEntryDescriptionProc)
+        {
+            ListUi->GetEntryDescriptionProc(ListEntry,
+                                            ListUi->CurrentItemText,
+                                            ARRAYSIZE(ListUi->CurrentItemText));
+        }
+
+        if ((strlen(ListUi->CurrentItemText) > 0) && (tolower(ListUi->CurrentItemText[0]) == AsciiChar))
         {
             Flag = TRUE;
             break;
         }
 
-        if (GenericList->CurrentEntry->Entry.Flink == &GenericList->ListHead)
+        if (List->CurrentEntry->Entry.Flink == &List->ListHead)
             break;
 
-        ScrollDownGenericList(GenericList);
-        ListEntry = GenericList->CurrentEntry;
+        ScrollDownGenericList(ListUi);
+        ListEntry = List->CurrentEntry;
     }
 
     if (!Flag)
     {
-        while (GenericList->CurrentEntry->Entry.Blink != &GenericList->ListHead)
+        while (List->CurrentEntry->Entry.Blink != &List->ListHead)
         {
-            if (GenericList->CurrentEntry != OldListEntry)
-                ScrollUpGenericList(GenericList);
+            if (List->CurrentEntry != OldListEntry)
+                ScrollUpGenericList(ListUi);
             else
                 break;
         }
     }
-End:
-    DrawListEntries(GenericList);
-    DrawScrollBarGenericList(GenericList);
-
-    GenericList->Redraw = TRUE;
-}
-
-
-VOID
-SaveGenericListState(
-    PGENERIC_LIST List)
-{
-    List->BackupEntry = List->CurrentEntry;
-}
 
+End:
+    DrawListEntries(ListUi);
+    DrawScrollBarGenericList(ListUi);
 
-VOID
-RestoreGenericListState(
-    PGENERIC_LIST List)
-{
-    List->CurrentEntry = List->BackupEntry;
+    ListUi->Redraw = TRUE;
 }
 
 /* EOF */