/*}}}*/ int process_list(char **x)/*{{{*/ { struct list_options options; int options_done = 0; int any_paths = 0; char index_buffer[256]; char *y; enum Priority prio = PRI_NORMAL, prio_to_use, node_prio; int prio_set = 0; time_t now = time(NULL); unsigned char *hits; int node_index, n_nodes; options.monochrome = 0; options.show_all = 0; options.show_postponed = 0; options.verbose = 0; options.set_depth = 0; if ( (getenv("TDL_LIST_MONOCHROME") != NULL) || (isatty(STDOUT_FILENO) == 0) ) { options.monochrome = 1; } /* Initialisation to support searching */ node_index = 0; allocate_indices(&top, &node_index); n_nodes = node_index; hits = n_nodes ? new_array(unsigned char, n_nodes) : NULL; /* all nodes match until proven otherwise */ memset(hits, 1, n_nodes); while ((y = *x) != 0) { /* An argument starting '1' or '+1' or '+-1' (or '-1' after '--') is * treated as the path of the top node to show */ if (isdigit(y[0]) || (y[0] == '.') || (options_done && (y[0] == '-') && isdigit(y[1])) || ((y[0] == '+') && (isdigit(y[1]) || ((y[1] == '-' && isdigit(y[2])))))) { struct node *n = lookup_node(y, 0, NULL); int summarise_kids; if (!n) return -1; any_paths = 1; index_buffer[0] = '\0'; strcat(index_buffer, y); summarise_kids = (options.set_depth && (options.depth==0)); if (hits[n->iscratch]) { print_details(n, 0, summarise_kids, &options, index_buffer, now); } if (!options.set_depth || (options.depth > 0)) { node_prio = n->priority; /* If the priority has been set on the cmd line, always use that. * Otherwise, use the priority from the specified node, _except_ when * that is higher than normal, in which case use normal. */ prio_to_use = (prio_set) ? prio : ((node_prio > prio) ? prio : node_prio); list_chain(&n->kids, INDENT_TAB, 0, &options, index_buffer, prio_to_use, now, hits); } } else if ((y[0] == '-') && (y[1] == '-')) { options_done = 1; } else if (y[0] == '-') { while (*++y) { switch (*y) { case 'v': options.verbose = 1; break; case 'a': options.show_all = 1; break; case 'm': options.monochrome = 1; break; case 'p': options.show_postponed = 1; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': options.set_depth = 1; options.depth = (*y) - '1'; break; default: fprintf(stderr, "Unrecognized option : -%c\n", *y); break; } } } else if (y[0] == '/') { /* search expression */ merge_search_condition(hits, n_nodes, y+1); } else { int error; prio = parse_priority(y, &error); if (error < 0) return error; prio_set = 1; } x++; } colours_init(&options); if (!any_paths) { struct node *narrow_top = get_narrow_top(); if (narrow_top) { index_buffer[0] = 0; if (hits[narrow_top->iscratch]) { int summarise_kids = (options.set_depth && (options.depth==0)); print_details(narrow_top, 0, summarise_kids, &options, index_buffer, now); } if (!options.set_depth || (options.depth > 0)) { list_chain(&narrow_top->kids, 0, 1, &options, index_buffer, prio, now, hits); } } else { index_buffer[0] = 0; list_chain(&top, 0, 0, &options, index_buffer, prio, now, hits); } } if (hits) free(hits); return 0; }
int main(int argc, char *argv[]) { /* gui structures */ struct gui_state gstate; struct gui_dialog_info dialog; struct gui_dialog_item dialog_msg; /* temps */ int c; int yn_selected; int res; int next_index; /* status */ int running; unsigned tick; /* global options */ /* int server; */ /* constants */ const int check[] = {0x6E, 0x69, 0x67, 0x67, 0x61}; #ifdef USING_WINDOWS /* windows-only vars */ HANDLE console_buffer; CONSOLE_SCREEN_BUFFER_INFO old_console_info; COORD console_size; SMALL_RECT console_window; LPTSTR error_string = NULL; DWORD error; /* get console handle */ console_buffer = GetStdHandle(STD_OUTPUT_HANDLE); /* store old console information */ res = GetConsoleScreenBufferInfo(console_buffer, &old_console_info); if (!res) { error = GetLastError(); res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, res, 0, error_string, 256, NULL); if (!res || error_string == NULL) { fprintf(stderr, "Setting console size to maximum of (%d, %d) failed, error code %d\n", console_size.X, console_size.Y, (int) error); } else { fprintf(stderr, "Setting console size to maximum of (%d, %d) failed:\n%s\n", console_size.X, console_size.Y, error_string); } return -1; } /* make console fill the screen */ console_size = GetLargestConsoleWindowSize(console_buffer); console_size.X -= 2; console_size.Y -= 2; res = SetConsoleScreenBufferSize(console_buffer, console_size); if (!res) { error = GetLastError(); res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, res, 0, error_string, 256, NULL); if (!res || error_string == NULL) { fprintf(stderr, "Setting console size to maximum of (%d, %d) failed, error code %d\n", console_size.X, console_size.Y, (int) error); } else { fprintf(stderr, "Setting console size to maximum of (%d, %d) failed:\n%s\n", console_size.X, console_size.Y, error_string); } return -1; } console_window.Left = 0; console_window.Top = 0; console_window.Right = console_size.X - 1; console_window.Bottom = console_size.Y - 1; res = SetConsoleWindowInfo(console_buffer, TRUE, &console_window); if (!res) { error = GetLastError(); res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, res, 0, error_string, 256, NULL); if (!res || error_string == NULL) { fprintf(stderr, "Setting console size to maximum of (%d, %d) failed, error code %d\n", console_size.X, console_size.Y, (int) error); } else { fprintf(stderr, "Setting console size to maximum of (%d, %d) failed:\n%s\n", console_size.X, console_size.Y, error_string); } return -1; } #endif /* process args (none supported currently) */ if (argc > 1) { fprintf(stderr, "unrecognised argument(s)\n"); return -1; } /* init curses */ initscr(); /* give warning dialog if colours are not supported */ if (has_colors() == FALSE) { /* set up message */ dialog_msg.type = GUI_DIALOG_ITEM_MESSAGE; dialog_msg.str = "Your terminal doesn't support colours. This will look REALLY weird. Continue? (y/n)"; /* set up dialog info */ dialog.items = &dialog_msg; dialog.num_items = 1; dialog.title = "No colours!"; dialog.centered = 1; dialog.autosize = 1; /* render dialog */ gui_render_dialog(&dialog, -1); /* ask for y/n */ yn_selected = 0; while (!yn_selected) { c = wgetch(stdscr); /* continue as normal if 'y' hit */ if (c == 'y' || c == 'Y') { yn_selected = 1; /* quit program if 'n' hit */ } else if (c == 'n' || c == 'N') { erase(); refresh(); endwin(); return 0; } } /* if colours are supported, init them */ } else { start_color(); colours_init(); } /* non-blocking read */ timeout(0); /* F-key support */ keypad(stdscr, TRUE); /* no line buffering */ raw(); /* detect return key */ nonl(); /* non-echoing getch */ noecho(); /* fill GUI state with default attributes */ gui_default_state(&gstate); /* main loop */ running = 1; tick = 0; next_index = 0; while (running) { ++tick; /* push GUI to screen */ res = gui_render(&gstate); if (res != 0) { endwin(); fprintf(stderr, "tick %d:\ngui_render failed\n", tick); return -1; } /* receive input (ERR received if none) */ c = wgetch(stdscr); /* none received, back to top */ if (c == ERR) { continue; } /* key combination check algorithm (no effect yet) */ if (c == check[next_index]) { ++next_index; if (next_index == 5) { next_index = 0; } } else { next_index = 0; } switch (c) { case 'q': /* send to quit confirmation, if already there then quit */ if (gstate.focus != GUI_FOCUS_QUIT_CONFIRM) { gstate.focus = GUI_FOCUS_QUIT_CONFIRM; } else { running = 0; } break; /* curses seems to use \r instead of KEY_ENTER */ case '\r': switch (gstate.focus) { case GUI_FOCUS_MAIN_MENU: if (gstate.selected_item >= gstate.main_menu_dialog.num_items) { endwin(); fprintf(stderr, "Index of selected dialog item (%d) out of range (main menu), max is %d\n", gstate.selected_item, gstate.main_menu_dialog.num_items); return -1; } gstate.main_menu_dialog.items[gstate.selected_item].callback(&gstate, NULL); break; case GUI_FOCUS_QUIT_CONFIRM: running = 0; default: break; } break; case KEY_UP: switch (gstate.focus) { case GUI_FOCUS_MAIN_MENU: --gstate.selected_item; if (gstate.selected_item < 0) { gstate.selected_item = gstate.main_menu_dialog.num_items - 1; } default: break; } break; case KEY_DOWN: switch (gstate.focus) { case GUI_FOCUS_MAIN_MENU: ++gstate.selected_item; if (gstate.selected_item >= gstate.main_menu_dialog.num_items) { gstate.selected_item = 0; } default: break; } default: break; } } /* show end splash, quit curses and stop normally */ gui_render_endscreen(); timeout(-1); wgetch(stdscr); erase(); refresh(); endwin(); #ifdef USING_WINDOWS /* attempt to restore previous console size + position */ console_window = old_console_info.srWindow; SetConsoleWindowInfo(console_buffer, TRUE, &console_window); console_size = old_console_info.dwSize; SetConsoleScreenBufferSize(console_buffer, console_size); /* clear */ system("cls"); #endif return 0; }