diff options
author | nwhitehorn <nwhitehorn@FreeBSD.org> | 2011-01-12 14:55:02 +0000 |
---|---|---|
committer | nwhitehorn <nwhitehorn@FreeBSD.org> | 2011-01-12 14:55:02 +0000 |
commit | 3d4e8889889e5e36302454225999f7e146d3219c (patch) | |
tree | fa315b999f531039df54ab7af8e99f7e8daad77c /gnu/lib/libdialog/tree.c | |
parent | b905920a72950a63c9782b4911d252bfac08db6e (diff) | |
download | FreeBSD-src-3d4e8889889e5e36302454225999f7e146d3219c.zip FreeBSD-src-3d4e8889889e5e36302454225999f7e146d3219c.tar.gz |
Update dialog to version 20100428. This changes the license under which
dialog is distributed from GPLv2 to LGPLv2 and introduces a number of new
features and a new and better libdialog API. The existing libdialog will
be kept temporarily as libodialog for compatibility purposes until sade,
sysinstall and tzsetup have been either updated or replaced.
__FreeBSD_version is now 900030.
Discussed on: -current
Approved by: core
Obtained from: http://invisible-island.net/dialog
Diffstat (limited to 'gnu/lib/libdialog/tree.c')
-rw-r--r-- | gnu/lib/libdialog/tree.c | 1133 |
1 files changed, 0 insertions, 1133 deletions
diff --git a/gnu/lib/libdialog/tree.c b/gnu/lib/libdialog/tree.c deleted file mode 100644 index ceacf05..0000000 --- a/gnu/lib/libdialog/tree.c +++ /dev/null @@ -1,1133 +0,0 @@ -/* - * tree.c -- implements the 'tree' interface element for libdialog - * - * Author: Anatoly A. Orehovsky (tolik@mpeks.tomsk.su) - * - * Copyright (c) 1997, Anatoly A. Orehovsky - * 09/28/98 - patched by Anatoly A. Orehovsky (smart_tree()) - * - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <stdlib.h> -#include <strings.h> -#include <stdio.h> -#include <dialog.h> -#include "dialog.priv.h" -#include <ncurses.h> - -/* static utils for make tree */ -struct leaf { - unsigned char *name; /* name of leaf */ - unsigned char *branches; /* branches that going by leaf */ - unsigned char slip; /* slip of leaf*/ - int shift; /* shift relative root of tree */ -}; - -static int mk_slip(struct leaf array[], int arr_size, - int number, int shift); - -/* make tree from file - * - * filename - name of file with like find(1) output - * p_names - pointer to array of strings - * p_size - pointer to size of array - * FS - fields separator - * p_array - pointer to array of leafs - * - * return values: - * 0 - ok and names by p_names, size by p_size, array by p_array set - * -1 - memory allocation error (errno set) - */ - -static int mk_ftree(char *filename, - unsigned char ***p_names, int *p_size, unsigned char FS, - struct leaf **p_array); - -/* make tree from array - * - * names - array of strings - * size - size of array - * FS - fields separator - * p_array - pointer to array of leafs - * - * return values: - * 0 - ok and array by p_array set - * -1 - memory allocation error (errno set) - */ - -static int mk_tree(unsigned char **names, int size, unsigned char FS, - struct leaf **p_array); - -/* free memory from tree (leafs) - * - * return values: - * nothing - */ - -static void free_leafs(struct leaf *array, int size); - -/* free memory from source data for tree (names) - * - * return values: - * if 0 <= choice <= size - pointer to name from names, - * and memory for name not released (must be freed later) - * else - NULL (recomended choice -1 for it) - */ - -static unsigned char *free_names(unsigned char **names, - int size, int choice); - -/* end of static utils for make tree */ - -/* static utils for ftree */ - -/* control struct for queue */ -struct queue { - int size; /* size of queue */ - struct m_queue *first; /* begin of queue */ - struct m_queue *last; /* end of queue */ -}; - -/* queue member */ -struct m_queue { - void *pointer; /* queue member */ - struct m_queue *next; /* next queue member */ -}; - -/* init struct queue by zeros */ -static void init_queue(struct queue *queue); - -/* add pointer to queue */ -/* return - pointer or NULL if error */ -static void *p2_queue(struct queue *queue, void *pointer); - -/* get first from queue */ -/* return - pointer or NULL if queue is empty */ -static void *first_queue(struct queue *queue); - -/* make zero terminated array from queue */ -/* return - pointer to array or NULL if error */ -static void **q2arr(struct queue *queue, int depth); - -/* smart_tree (for like find(1) with -d flag output compliance) */ -/* return - not NULL or NULL if malloc error */ -static unsigned char *smart_tree(struct queue *queue, unsigned char FS, - unsigned char *current, - unsigned char *prev); - -/* end of static utils for ftree */ - -/* static utils for saved_tree */ - -/* saved values for unique tree */ -struct saved_tree { - unsigned char **names; /* names + */ - int size; /* size + */ - unsigned char FS; /* FS + */ - int height; /* height + */ - int width; /* width + */ - int menu_height; /* menu_height - unique for treebox ? */ - int ch; /* saved ch - choice */ - int sc; /* saved sc - scroll */ -}; - -/* search saved tree within queue */ -/* return - struct saved_tree * or NULL if not found */ -static struct saved_tree *search_saved_tree(struct queue *queue, - unsigned char **names, - int size, - unsigned char FS, - int height, - int width, - int menu_height); - -/* end of static utils for saved_tree */ - -static void print_item(WINDOW *win, struct leaf item, int choice, int selected); - -static void print_position(WINDOW *win, int x, int y, - int cur_pos, int size); - -static int menu_width, item_x; - -static int dialog_treemenu(unsigned char *title, unsigned char *prompt, - int height, int width, int menu_height, - int item_no, struct leaf items[], - int *result, - int *ch, int *sc); - -/* - * Display a menu for choosing among a number of options - */ -static -int dialog_treemenu(unsigned char *title, unsigned char *prompt, - int height, int width, int menu_height, - int item_no, struct leaf items[], - int *result, - int *ch, int *sc) -{ - int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0, - l, scroll = 0, max_choice, redraw_menu = FALSE; - WINDOW *dialog, *menu; - - if (ch) /* restore menu item info */ - choice = *ch; - if (sc) - scroll = *sc; - - max_choice = MIN(menu_height, item_no); - - item_x = 0; - /* Find length of longest item in order to center menu */ - for (i = 0; i < item_no; i++) { - l = strlen(items[i].name) + strlen(items[i].branches) * 4 + 4; - item_x = MAX(item_x, l); - } - - if (height < 0) - height = strheight(prompt)+menu_height+4+2; - if (width < 0) { - i = strwidth(prompt); - j = ((title != NULL) ? strwidth(title) : 0); - width = MAX(i,j); - width = MAX(width,item_x+4)+4; - } - width = MAX(width,24); - - if (width > COLS) - width = COLS; - if (height > LINES) - height = LINES; - /* center dialog box on screen */ - x = (COLS - width)/2; - y = (LINES - height)/2; - -#ifdef HAVE_NCURSES - if (use_shadow) - draw_shadow(stdscr, y, x, height, width); -#endif - dialog = newwin(height, width, y, x); - if (dialog == NULL) { - endwin(); - fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); - exit(1); - } - keypad(dialog, TRUE); - - draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); - wattrset(dialog, border_attr); - wmove(dialog, height-3, 0); - waddch(dialog, ACS_LTEE); - for (i = 0; i < width-2; i++) - waddch(dialog, ACS_HLINE); - wattrset(dialog, dialog_attr); - waddch(dialog, ACS_RTEE); - wmove(dialog, height-2, 1); - for (i = 0; i < width-2; i++) - waddch(dialog, ' '); - - if (title != NULL) { - wattrset(dialog, title_attr); - wmove(dialog, 0, (width - strlen(title))/2 - 1); - waddch(dialog, ' '); - waddstr(dialog, title); - waddch(dialog, ' '); - } - wattrset(dialog, dialog_attr); - wmove(dialog, 1, 2); - print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE); - - menu_width = width-6; - getyx(dialog, cur_y, cur_x); - box_y = cur_y + 1; - box_x = (width - menu_width)/2 - 1; - - /* create new window for the menu */ - menu = subwin(dialog, menu_height, menu_width, y + box_y + 1, x + box_x + 1); - if (menu == NULL) { - endwin(); - fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", menu_height,menu_width,y+box_y+1,x+box_x+1); - exit(1); - } - keypad(menu, TRUE); - - /* draw a box around the menu items */ - draw_box(dialog, box_y, box_x, menu_height+2, menu_width+2, menubox_border_attr, menubox_attr); - - item_x = 1; - - /* Print the menu */ - for (i = 0; i < max_choice; i++) - print_item(menu, items[(scroll+i)], i, i == choice); - wnoutrefresh(menu); - print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y); - print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); - - display_helpline(dialog, height-1, width); - - x = width/2-11; - y = height-2; - print_button(dialog, "Cancel", y, x+14, FALSE); - print_button(dialog, " OK ", y, x, TRUE); - - wrefresh(dialog); - - while (key != ESC) { - key = wgetch(dialog); - /* Check if key pressed matches first character of any item tag in menu */ - - if (key == KEY_UP || key == KEY_DOWN || key == '-' || key == '+') { - if (key == KEY_UP || key == '-') { - if (!choice) { - if (scroll) { -#ifdef BROKEN_WSCRL - /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation - violation when scrolling windows of height = 4, so scrolling is not - used for now */ - scroll--; - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - /* Reprint menu to scroll down */ - for (i = 0; i < max_choice; i++) - print_item(menu, items[(scroll+i)], i, i == choice); - -#else - - /* Scroll menu down */ - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - if (menu_height > 1) { - /* De-highlight current first item before scrolling down */ - print_item(menu, items[scroll], 0, FALSE); - scrollok(menu, TRUE); - wscrl(menu, -1); - scrollok(menu, FALSE); - } - scroll--; - print_item(menu, items[scroll], 0, TRUE); -#endif - wnoutrefresh(menu); - print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y); - print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); - wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ - wrefresh(dialog); - } - continue; /* wait for another key press */ - } - else - i = choice - 1; - } - else if (key == KEY_DOWN || key == '+') { - if (choice == max_choice - 1) { - if (scroll+choice < item_no-1) { -#ifdef BROKEN_WSCRL - /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation - violation when scrolling windows of height = 4, so scrolling is not - used for now */ - scroll++; - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - /* Reprint menu to scroll up */ - for (i = 0; i < max_choice; i++) - print_item(menu, items[(scroll+i)], i, i == choice); - -#else - - /* Scroll menu up */ - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - if (menu_height > 1) { - /* De-highlight current last item before scrolling up */ - print_item(menu, items[(scroll+max_choice-1)], max_choice-1, FALSE); - scrollok(menu, TRUE); - scroll(menu); - scrollok(menu, FALSE); - } - scroll++; - print_item(menu, items[(scroll+max_choice-1)], max_choice-1, TRUE); -#endif - wnoutrefresh(menu); - print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y); - print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); - wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ - wrefresh(dialog); - } - continue; /* wait for another key press */ - } - else - i = choice + 1; - } - - if (i != choice) { - /* De-highlight current item */ - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - print_item(menu, items[(scroll+choice)], choice, FALSE); - - /* Highlight new item */ - choice = i; - print_item(menu, items[(scroll+choice)], choice, TRUE); - wnoutrefresh(menu); - print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); - wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ - wrefresh(dialog); - } - continue; /* wait for another key press */ - } - - /* save info about menu item position */ - if (ch) - *ch = choice; - if (sc) - *sc = scroll; - - switch (key) { - case KEY_PPAGE: - case 'B' : - case 'b' : - if (scroll > menu_height) { /* can we go up? */ - scroll -= (menu_height); - } else { - scroll = 0; - } - redraw_menu = TRUE; - break; - case KEY_NPAGE: - case 'F' : - case 'f' : - if (scroll + menu_height >= item_no-1 - menu_height) { /* can we go down a full page? */ - scroll = item_no - menu_height; - if (scroll < 0) scroll = 0; - } else { - scroll += menu_height; - } - redraw_menu = TRUE; - break; - case KEY_HOME: - case 'g' : - scroll = 0; - choice = 0; - redraw_menu = TRUE; - break; - case KEY_END: - case 'G' : - scroll = item_no - menu_height; - if (scroll < 0) scroll = 0; - choice = max_choice - 1; - redraw_menu = TRUE; - break; - case 'O': - case 'o': - delwin(dialog); - *result = scroll+choice; - return 0; - case 'C': - case 'c': - delwin(dialog); - return 1; - case KEY_BTAB: - case TAB: - case KEY_LEFT: - case KEY_RIGHT: - if (!button) { - button = 1; /* Indicates "Cancel" button is selected */ - print_button(dialog, " OK ", y, x, FALSE); - print_button(dialog, "Cancel", y, x+14, TRUE); - } - else { - button = 0; /* Indicates "OK" button is selected */ - print_button(dialog, "Cancel", y, x+14, FALSE); - print_button(dialog, " OK ", y, x, TRUE); - } - wrefresh(dialog); - break; - case ' ': - case '\r': - case '\n': - delwin(dialog); - if (!button) - *result = scroll+choice; - return button; - case ESC: - break; - case KEY_F(1): - case '?': - display_helpfile(); - break; - } - if (redraw_menu) { - for (i = 0; i < max_choice; i++) { - print_item(menu, items[(scroll+i)], - i, i == choice); - } - wnoutrefresh(menu); - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, item_x, cur_x, cur_y); - print_position(dialog, box_x+menu_width, box_y+menu_height, scroll+choice, item_no); - wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ - wrefresh(dialog); - redraw_menu = FALSE; - } - } - - delwin(dialog); - return -1; /* ESC pressed */ -} -/* End of dialog_treemenu() */ - - -/* - * Print menu item - */ -static void print_item(WINDOW *win, struct leaf item, int choice, int selected) -{ - int i, j = menu_width - 2; - char *branches = item.branches; - - /* Clear 'residue' of last item */ - wattrset(win, menubox_attr); - wmove(win, choice, 0); - for (i = 0; i < menu_width; i++) - waddch(win, ' '); - wmove(win, choice, item_x); - - while(*branches && j) - { - switch (*branches++) { - case ' ' : waddch(win, ' '); - break; - case '|' : waddch(win, ACS_VLINE); - } - - j--; - i = 3; - while(i-- && j) - { - waddch(win, ' '); - j--; - } - } - - if (j) - { - switch (item.slip) { - case '+' : waddch(win, ACS_LTEE); - break; - case '`' : waddch(win, ACS_LLCORNER); - } - j--; - } - - i = 3; - while(i-- && j) - { - waddch(win, ACS_HLINE); - j--; - } - - wattrset(win, selected ? item_selected_attr : item_attr); - if (j) - waddnstr(win, item.name, j); -} -/* End of print_item() */ - -/* - * Print current position - */ -static void print_position(WINDOW *win, int x, int y, - int cur_pos, int size) -{ - int percent; - - wattrset(win, position_indicator_attr); - percent = cur_pos == size - 1 ? 100 : (cur_pos * 100)/(size - 1); - wmove(win, y + 1, x - 6); - wprintw(win, "(%3d%%)", percent); -} -/* End of print_position() */ - -/* - * Display a tree menu from file - * - * filename - file with like find(1) output - * FS - fields separator - * title - title of dialog box - * prompt - prompt text into dialog box - * height - height of dialog box - * width - width of dialog box - * menu_height - height of menu box - * result - pointer to char array - * - * return values: - * -1 - ESC pressed - * 0 - Ok, result set (must be freed later) - * 1 - Cancel - */ - -int dialog_ftree(unsigned char *filename, unsigned char FS, - unsigned char *title, unsigned char *prompt, - int height, int width, int menu_height, - unsigned char **result) -{ - int retcode, choice, size; - struct leaf *items; - unsigned char **names; - - if (mk_ftree(filename, &names, &size, FS, &items)) - { - perror("dialog_ftree"); - end_dialog(); - exit(-1); - } - - if (!size) - { - fprintf(stderr, "\ndialog_ftree: file %s is empty\n", filename); - end_dialog(); - exit(-1); - } - - retcode = dialog_treemenu(title, prompt, height, width, menu_height, - size, items, &choice, NULL, NULL); - - free_leafs(items, size); - - if (!retcode) - *result = free_names(names, size, choice); - else - (void)free_names(names, size, -1); - - return retcode; -} -/* End of dialog_ftree() */ - -/* - * Display a tree menu from array - * - * names - array with like find(1) output - * size - size of array - * FS - fields separator - * title - title of dialog box - * prompt - prompt text into dialog box - * height - height of dialog box - * width - width of dialog box - * menu_height - height of menu box - * result - pointer to char array - * - * return values: - * -1 - ESC pressed - * 0 - Ok, result set - * 1 - Cancel - */ - -int dialog_tree(unsigned char **names, int size, unsigned char FS, - unsigned char *title, unsigned char *prompt, - int height, int width, int menu_height, - unsigned char **result) -{ - int retcode, choice; - struct leaf *items; - struct saved_tree *st; - static struct queue *q_saved_tree = NULL; - - if (!size) - { - fprintf(stderr, "\ndialog_tree: source array is empty\n"); - end_dialog(); - exit(-1); - } - - if (mk_tree(names, size, FS, &items)) - { - perror("dialog_tree"); - end_dialog(); - exit(-1); - } - -/* is tree saved ? */ - if (!(st = search_saved_tree(q_saved_tree, names, - size, FS, - height, width, menu_height))) { - if (!q_saved_tree) { - if (!(q_saved_tree = - calloc(sizeof (struct queue), 1))) { - perror("dialog_tree"); - end_dialog(); - exit(-1); - } - } - - if (!(st = calloc(sizeof (struct saved_tree), 1))) { - perror("dialog_tree"); - end_dialog(); - exit(-1); - } - - st->names = names; - st->size = size; - st->FS = FS; - st->height = height; - st->width = width; - st->menu_height = menu_height; - - if (!p2_queue(q_saved_tree, st)) { - perror("dialog_tree"); - end_dialog(); - exit(-1); - } - } - - retcode = dialog_treemenu(title, prompt, height, width, menu_height, - size, items, &choice, - &(st->ch), &(st->sc)); - - free_leafs(items, size); - - if (!retcode) - *result = names[choice]; - - return retcode; -} -/* End of dialog_tree() */ - -/* utils for ftree */ - -/* init struct queue by zeros */ -static void -init_queue(struct queue *queue) -{ - bzero((void *)queue, sizeof(struct queue)); -} - -/* add pointer to queue */ -/* return - pointer or NULL if error */ -static void * -p2_queue(struct queue *queue, void *pointer) -{ - if (!queue) - return NULL; - - if (!queue->first) - { - if (!(queue->first = queue->last = - calloc(1, sizeof(struct m_queue)))) - return NULL; - - } - else - { - if (!(queue->last->next = - calloc(1, sizeof(struct m_queue)))) - return NULL; - - queue->last = queue->last->next; - } - - queue->size++; - return queue->last->pointer = pointer; -} - -/* get first from queue */ -/* return - pointer or NULL if queue is empty */ -static void * -first_queue(struct queue *queue) -{ - void *retval; - struct m_queue *new_first; - - if (!queue || - !queue->first || - !queue->size) - return NULL; - - retval = queue->first->pointer; - new_first = queue->first->next; - free(queue->first); - queue->first = new_first; - queue->size--; - - return retval; - -} - -/* make zero terminated array from queue */ -/* return - pointer to array or NULL if error */ -static void ** -q2arr(struct queue *queue, int depth) -{ - void **mono, **end; - - if (!queue || - !queue->first || - !queue->size) - return NULL; - - /* memory allocation for array */ - if (!(mono = end = malloc(depth * sizeof(void *) + 1))) - return NULL; - - while(depth--) - { - if (!(*end++ = first_queue(queue))) - break; - } - - *end = NULL; - - return mono; - -} - -/* - * smart_tree (for like find(1) with -d flag output compliance) - * - * return values: - * NULL - malloc error - * not NULL - ok - * - */ -static -unsigned char * -smart_tree(struct queue *queue, - unsigned char FS, - unsigned char *current, - unsigned char *prev) { - unsigned char *pcurrent = current, *pprev = prev, *toqueue; - register char break_flag = 0; - - while(*pcurrent && *pprev) { - if (*pcurrent == *pprev) { - pcurrent++; - pprev++; - } - else { - break_flag = 1; - break; - } - } - - if (!*pprev || break_flag) { - if (*pcurrent == FS) { - pcurrent++; - - if ((!*prev) && (*pcurrent)) { - unsigned char tchar = *pcurrent; - - *pcurrent = '\0'; - if (!(toqueue = strdup(current))) { - *pcurrent = tchar; - return NULL; - } - if (!p2_queue(queue, toqueue)) { - *pcurrent = tchar; - return NULL; - } - *pcurrent = tchar; - } - } - - while(*pcurrent) { - if (*pcurrent == FS) { - *pcurrent = '\0'; - if (!(toqueue = strdup(current))) { - *pcurrent = FS; - return NULL; - } - if (!p2_queue(queue, toqueue)) { - *pcurrent = FS; - return NULL; - } - *pcurrent = FS; - } - pcurrent++; - } - if (!p2_queue(queue, current)) - return NULL; - } - return current; -} - -/* end of utils for ftree */ - -/* utils for make tree */ - -/* if error - return -1 */ -static -int -mk_slip(struct leaf array[], int arr_size, int number, int shift) -{ - int t_number; - int t_shift; - - if (number > arr_size - 1) - return number - 1; - - t_shift = shift; - - if (!(array[number].branches = calloc(1, t_shift + 1))) - return -1; - - (void)memset(array[number].branches, ' ', t_shift); - - t_number = number; - - while (array[number].shift < array[t_number + 1].shift) - { - t_number = mk_slip(array, arr_size, t_number + 1, t_shift + 1); - if (t_number < 0) - return -1; - if (t_number == arr_size - 1) - break; - } - - if (array[number].shift == array[t_number + 1].shift) - array[number].slip = '+'; - - if ((array[number].shift > array[t_number + 1].shift) || - t_number == arr_size - 1) - array[number].slip = '`'; - - return t_number; - -} /* mk_slip() */ - -/* make tree from file - * - * filename - name of file with like find(1) output - * p_names - pointer to array of strings - * p_size - pointer to size of array - * FS - fields separator - * p_array - pointer to array of leafs - * - * return values: - * 0 - ok and names by p_names, size by p_size, array by p_array set - * -1 - memory allocation error (errno set) - */ - -static -int -mk_ftree(char *filename, - unsigned char ***p_names, int *p_size, unsigned char FS, - struct leaf **p_array) -{ - int NR; /* number of input records */ - struct queue queue; - unsigned char *string, *sstring = ""; - unsigned char **names; - - FILE *input_file; - - if (!(input_file = fopen(filename, "r"))) - return -1; - - init_queue(&queue); - - if (!(string = malloc(BUFSIZ))) - return -1; - - /* read input file into queue */ - while(fgets(string, BUFSIZ, input_file)) - { - if (strchr(string, '\n')) - *strchr(string, '\n') = '\0'; - - if (!(string = realloc(string, strlen(string) + 1))) - return -1; - - if (!smart_tree(&queue, FS, string, sstring)) - return -1; - sstring = string; - - if (!(string = malloc(BUFSIZ))) - return -1; - } /* read input file into queue */ - - if (fclose(input_file) == EOF) - return -1; - - if (!(NR = queue.size)) - { - *p_size = 0; - return 0; - } - - /* make array from queue */ - if (!(names = (unsigned char **)q2arr(&queue, NR))) - return -1; - - *p_names = names; - *p_size = NR; - - /* make tree from array */ - return mk_tree(names, NR, FS, p_array); - -} /* mk_ftree */ - -/* make tree from array - * - * names - array of strings - * size - size of array - * FS - fields separator - * p_array - pointer to array of leafs - * - * return values: - * 0 - ok and array by p_array set - * -1 - memory allocation error (errno set) - */ - -static -int -mk_tree(unsigned char **names, int size, unsigned char FS, - struct leaf **p_array) -{ - int i; - struct leaf *array; - - /* make array of leafs */ - if (!(array = calloc(size, sizeof(struct leaf)))) - return -1; - - /* init leafs */ - for (i = 0; i < size; i++) - { - unsigned char *in_string, *name; - int shift = 0; - - in_string = name = names[i]; - while(*in_string) - { - if (*in_string == FS) { - if (!i && !*(in_string + 1)) - name = in_string; - else - { - shift++; - name = in_string + 1; - } - } - in_string++; - } - array[i].name = name; - array[i].shift = shift; - array[i].slip = '\0'; - array[i].branches = NULL; - } /* init leafs */ - - /* make slips */ - for (i = 0;i < size; i++) - { - i = mk_slip(array, size, i, 0); - if (i < 0) - return -1; - } /* make slips */ - - /* make branches */ - for (i = 1;i < size; i++) - { - unsigned char *src = array[i - 1].branches; - unsigned char *dst = array[i].branches; - - while(*src && *dst) - *dst++ = *src++; - - if (*dst) - switch (array[i - 1].slip) { - case '+' : *dst = '|'; - break; - case '`' : *dst = ' '; - } - } /* make branches */ - - *p_array = array; - return 0; - -} /* mk_tree() */ - -/* free memory from tree (leafs) - * - * return values: - * nothing - */ - -static -void -free_leafs(struct leaf *array, int size) -{ - struct leaf *p_array = array; - - while (size--) - free(array++->branches); - - free(p_array); -} /* free_leafs() */ - -/* free memory from source data for tree (names) - * - * return values: - * if 0 <= choice <= size - pointer to name from names, - * and memory for name not released (must be freed later) - * else - NULL (recomended choice -1 for it) - */ - -static -unsigned char * -free_names(unsigned char **names, int size, int choice) -{ - unsigned char *retval = NULL; - unsigned char **p_names = names; - - while (size--) - { - if (!choice--) - retval = *names++; - else - free(*names++); - } - free(p_names); - return retval; -} /* free_names() */ - -/* end of utils for make tree */ - -/* static utils for saved_tree */ - -/* search saved tree within queue */ -/* return - struct *saved_tree or NULL if not found */ -static -struct saved_tree * -search_saved_tree(struct queue *queue, unsigned char **names, int size, - unsigned char FS, - int height, int width, - int menu_height) -{ - struct m_queue *member; - struct saved_tree *retval; - - if (!queue || !names || !FS || - !height || !width || !menu_height) - return NULL; - - if (!(member = queue->first)) - return NULL; - - while (member->next) { - retval = member->pointer; - if ((names == retval->names) && - (size == retval->size) && - (FS == retval->FS) && - (height == retval->height) && - (width == retval->width) && - (menu_height == retval->menu_height)) - return retval; - member = member->next; - } - retval = member->pointer; - if ((names == retval->names) && - (size == retval->size) && - (FS == retval->FS) && - (height == retval->height) && - (width == retval->width) && - (menu_height == retval->menu_height)) - return retval; - return NULL; -} - -/* end of static utils for saved_tree */ |