--- index.c.orig 2012-02-27 19:44:23.000000000 +0900 +++ index.c 2012-02-27 20:19:50.000000000 +0900 @@ -237,24 +237,28 @@ if (high_volume < volume) high_volume = volume; } return tmp; } static void index_register(PkgNodePtr top, char *where, IndexEntryPtr ptr) { PkgNodePtr p, q; + PkgNodePtr *pp; - for (q = NULL, p = top->kids; p; p = p->next) { + for (q = NULL, pp = &top->kids; (p = *pp); pp = &((*pp)->next)) { if (!strcmp(p->name, where)) { q = p; + *pp = q->next; + q->next = top->kids; + top->kids = q; break; } } if (!p) { /* Add new category */ q = new_pkg_node(where, PLACE); q->desc = fetch_desc(where); q->next = top->kids; top->kids = q; } @@ -429,27 +433,53 @@ { PkgNode tmp; tmp = *a; *a = *b; a->next = tmp.next; tmp.next = b->next; *b = tmp; } -/* Use a disgustingly simplistic bubble sort to put our lists in order */ +static int +index_compare(PkgNodePtr *p, PkgNodePtr *q) +{ + return strcmp((*p)->name, (*q)->name); +} + void index_sort(PkgNodePtr top) { PkgNodePtr p, q; + PkgNodePtr *pp; + PkgNodePtr *a; + int i, num = 0; /* Sort everything at the top level */ + + for (p = top->kids; p; p = p->next) + num++; + a = (PkgNodePtr *)malloc(sizeof(*a) * num); + if (a) { + i = 0; + for (p = top->kids; p; p = p->next) + a[i++] = p; + qsort(a, num, sizeof(*a), (void *)index_compare); + pp = &top->kids; + for (i = 0; i < num; i++) { + *pp = a[i]; + pp = &((*pp)->next); + } + *pp = NULL; + free(a); + } else + /* Use a disgustingly simplistic bubble sort to put our lists in order */ for (p = top->kids; p; p = p->next) { for (q = top->kids; q; q = q->next) { if (q->next && strcmp(q->name, q->next->name) > 0) swap_nodes(q, q->next); } } /* Now sub-sort everything n levels down */ for (p = top->kids; p; p = p->next) { if (p->kids) @@ -468,48 +498,72 @@ safe_free(p); } else /* Kludgy end sentinal */ n->name = NULL; } /* * Search for a given node by name, returning the category in if * tp is non-NULL. */ -PkgNodePtr -index_search(PkgNodePtr top, char *str, PkgNodePtr *tp) +static PkgNodePtr +index_search_sub(PkgNodePtr top, char *str, PkgNodePtr *tp, int move) { PkgNodePtr p, sp; + PkgNodePtr *pp; - for (p = top->kids; p && p->name; p = p->next) { + for (pp = &top->kids; (p = *pp) && p->name; pp = &((*pp)->next)) { if (p->type == PACKAGE) { /* If tp == NULL, we're looking for an exact package match */ - if (!tp && !strcmp(p->name, str)) + if (!tp && !strcmp(p->name, str)) { + if (move) { + *pp = p->next; + p->next = top->kids; + top->kids = p; + } return p; + } /* If tp, we're looking for both a package and a pointer to the place it's in */ if (tp && !strncmp(p->name, str, strlen(str))) { *tp = top; + if (move) { + *pp = p->next; + p->next = top->kids; + top->kids = p; + } return p; } } else if (p->kids) { /* The usual recursion-out-of-laziness ploy */ - if ((sp = index_search(p, str, tp)) != NULL) + if ((sp = index_search_sub(p, str, tp, move)) != NULL) return sp; } } if (p && !p->name) p = NULL; return p; } +PkgNodePtr +index_search(PkgNodePtr top, char *str, PkgNodePtr *tp) +{ + return index_search_sub(top, str, tp, 0); +} + +PkgNodePtr +index_search_move(PkgNodePtr top, char *str, PkgNodePtr *tp) +{ + return index_search_sub(top, str, tp, 1); +} + static int pkg_checked(dialogMenuItem *self) { ListPtrsPtr lists = (ListPtrsPtr)self->aux; PkgNodePtr kp = self->data, plist = lists->plist; int i; i = index_search(plist, kp->name, NULL) ? TRUE : FALSE; if (kp->type == PACKAGE && plist) { IndexEntryPtr ie = kp->data; @@ -621,20 +675,23 @@ hasPackages = TRUE; if ((len = strlen(kp->name)) > maxname) maxname = len; } } if (!n && plist) { msgConfirm("The %s menu is empty.", top->name); return DITEM_LEAVE_MENU; } + if (maxname > _MAX_DESC) + maxname = _MAX_DESC; + w = savescr(); while (1) { n = 0; curr = max = 0; use_helpline(NULL); use_helpfile(NULL); kp = top->kids; if (!hasPackages && plist) { nitems = item_add(nitems, "OK", NULL, NULL, NULL, NULL, NULL, NULL, &curr, &max); nitems = item_add(nitems, "Install", NULL, NULL, NULL, NULL, NULL, NULL, &curr, &max); @@ -768,21 +825,21 @@ * Done with the deps? Try to load the real m'coy. If iterating * through a multi-volume disc set fail the install if the package * is on a higher numbered volume to cut down on disc switches the * user needs to do, but indicate caller should continue processing * despite error return. Note this package was processed for the * current disc being checked. */ if (DITEM_STATUS(status) == DITEM_SUCCESS) { /* Prompt user if the package is not available on the current volume. */ - if(mediaDevice->type == DEVICE_TYPE_CDROM) { + if (mediaDevice && mediaDevice->type == DEVICE_TYPE_CDROM) { if (current_volume != 0 && id->volume > current_volume) { restorescr(w); id->vol_checked = current_volume; return DITEM_FAILURE | DITEM_CONTINUE; } while (id->volume != dev->volume) { if (!msgYesNo("This is disc #%d. Package %s is on disc #%d\n" "Would you like to switch discs now?\n", dev->volume, id->name, id->volume)) { DEVICE_SHUTDOWN(mediaDevice); @@ -810,21 +867,21 @@ PkgNodePtr found; IndexEntryPtr found_ie; SAFE_STRCPY(depends, ie->deps); for (todo = depends; todo != NULL; ) { space = index(todo, ' '); if (space != NULL) *space = '\0'; if (strlen(todo) > 0) { /* only non-empty dependencies */ - found = index_search(root, todo, NULL); + found = index_search_move(root, todo, NULL); if (found != NULL) { found_ie = found->data; if (add) ++found_ie->depc; else --found_ie->depc; } } if (space != NULL)