* Added a new list_insert_item_before() function that inserts a new item

before another one in the list.
* The video modes in the boot loader are now sorted (by resolution, larger
  resolution comes first). Doubled entries are automatically removed; this
  fixes bug #192.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16572 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-03-02 22:48:47 +00:00
parent 5370f52b15
commit d5062208bb
3 changed files with 134 additions and 64 deletions

View File

@ -1,7 +1,7 @@
/* /*
** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the OpenBeOS License. * Distributed under the terms of the MIT License.
*/ */
#ifndef KERNEL_LIST_H #ifndef KERNEL_LIST_H
#define KERNEL_LIST_H #define KERNEL_LIST_H
@ -50,6 +50,7 @@ extern void *list_get_next_item(struct list *list, void *item);
extern void *list_get_prev_item(struct list *list, void *item); extern void *list_get_prev_item(struct list *list, void *item);
extern void list_add_item(struct list *list, void *item); extern void list_add_item(struct list *list, void *item);
extern void list_remove_item(struct list *list, void *item); extern void list_remove_item(struct list *list, void *item);
extern void list_insert_item_before(struct list *list, void *before, void *item);
extern void *list_remove_head_item(struct list *list); extern void *list_remove_head_item(struct list *list);
extern void *list_remove_tail_item(struct list *list); extern void *list_remove_tail_item(struct list *list);
extern void list_move_to_list(struct list *sourceList, struct list *targetList); extern void list_move_to_list(struct list *sourceList, struct list *targetList);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@ -46,6 +46,102 @@ static bool sModeChosen;
static bool sSettingsLoaded; static bool sSettingsLoaded;
static int
compare_video_modes(video_mode *a, video_mode *b)
{
int compare = a->width - b->width;
if (compare != 0)
return compare;
compare = a->height - b->height;
if (compare != 0)
return compare;
// TODO: compare video_mode::mode?
return a->bits_per_pixel - b->bits_per_pixel;
}
/** Insert the video mode into the list, sorted by resolution and bit depth.
* Higher resolutions/depths come first.
*/
static void
add_video_mode(video_mode *videoMode)
{
video_mode *mode = NULL;
while ((mode = (video_mode *)list_get_next_item(&sModeList, mode)) != NULL) {
int compare = compare_video_modes(videoMode, mode);
if (compare == 0) {
// mode already exists
return;
}
if (compare > 0)
break;
}
list_insert_item_before(&sModeList, mode, videoMode);
}
static video_mode *
find_video_mode(int32 width, int32 height, int32 depth)
{
video_mode *mode = NULL;
while ((mode = (video_mode *)list_get_next_item(&sModeList, mode)) != NULL) {
if (mode->width == width
&& mode->height == height
&& mode->bits_per_pixel == depth) {
return mode;
}
}
return NULL;
}
static void
get_mode_from_settings(void)
{
if (sSettingsLoaded)
return;
void *handle = load_driver_settings("vesa");
if (handle == NULL)
return;
const driver_settings *settings = get_driver_settings(handle);
if (settings == NULL)
goto out;
sSettingsLoaded = true;
for (int32 i = 0; i < settings->parameter_count; i++) {
driver_parameter &parameter = settings->parameters[i];
if (!strcmp(parameter.name, "mode") && parameter.value_count > 2) {
// parameter found, now get its values
int32 width = strtol(parameter.values[0], NULL, 0);
int32 height = strtol(parameter.values[1], NULL, 0);
int32 depth = strtol(parameter.values[2], NULL, 0);
// search mode that fits
video_mode *mode = find_video_mode(width, height, depth);
if (mode != NULL)
sMode = mode;
}
}
out:
unload_driver_settings(handle);
}
// #pragma mark - vga
static void static void
vga_set_palette(const uint8 *palette, int32 firstIndex, int32 numEntries) vga_set_palette(const uint8 *palette, int32 firstIndex, int32 numEntries)
{ {
@ -189,7 +285,7 @@ vesa_init(vbe_info_block *info, video_mode **_standardMode)
} }
} }
list_add_item(&sModeList, videoMode); add_video_mode(videoMode);
} }
} else } else
TRACE(("(failed)\n")); TRACE(("(failed)\n"));
@ -344,60 +440,6 @@ video_mode_menu()
} }
static video_mode *
find_video_mode(int32 width, int32 height, int32 depth)
{
video_mode *mode = NULL;
while ((mode = (video_mode *)list_get_next_item(&sModeList, mode)) != NULL) {
if (mode->width == width
&& mode->height == height
&& mode->bits_per_pixel == depth) {
return mode;
}
}
return NULL;
}
static void
get_mode_from_settings(void)
{
if (sSettingsLoaded)
return;
void *handle = load_driver_settings("vesa");
if (handle == NULL)
return;
const driver_settings *settings = get_driver_settings(handle);
if (settings == NULL)
goto out;
sSettingsLoaded = true;
for (int32 i = 0; i < settings->parameter_count; i++) {
driver_parameter &parameter = settings->parameters[i];
if (!strcmp(parameter.name, "mode") && parameter.value_count > 2) {
// parameter found, now get its values
int32 width = strtol(parameter.values[0], NULL, 0);
int32 height = strtol(parameter.values[1], NULL, 0);
int32 depth = strtol(parameter.values[2], NULL, 0);
// search mode that fits
video_mode *mode = find_video_mode(width, height, depth);
if (mode != NULL)
sMode = mode;
}
}
out:
unload_driver_settings(handle);
}
static void static void
set_vga_mode(void) set_vga_mode(void)
{ {

View File

@ -1,7 +1,7 @@
/* /*
** Copyright 2003-2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the OpenBeOS License. * Distributed under the terms of the MIT License.
*/ */
#include <util/list.h> #include <util/list.h>
@ -156,6 +156,33 @@ list_remove_item(struct list *list, void *item)
} }
/** Inserts an item before another item in the list.
* If you pass NULL as \a before item, the item is added at the end of
* the list.
*/
void
list_insert_item_before(struct list *list, void *before, void *item)
{
list_link *beforeLink;
list_link *link;
if (before == NULL) {
list_add_item(list, item);
return;
}
beforeLink = GET_LINK(list, before);
link = GET_LINK(list, item);
link->prev = beforeLink->prev;
link->next = beforeLink;
beforeLink->prev->next = link;
beforeLink->prev = link;
}
/** Removes the first item in the list and returns it. /** Removes the first item in the list and returns it.
* Returns NULL if the list is empty. * Returns NULL if the list is empty.
*/ */