/* Shutdown pager P and prevent any future paging activity on it. */ void pager_shutdown (struct pager *p) { /* Sync and flush pager */ pager_sync (p, 1); pager_flush (p, 1); mutex_lock (&p->interlock); p->pager_state = SHUTDOWN; ports_destroy_right (p); mutex_unlock (&p->interlock); }
error_t diskfs_reload_global_state () { error_t err; pokel_flush (&global_pokel); pager_flush (diskfs_disk_pager, 1); /* libdiskfs is not responsible for inhibiting paging. */ err = inhibit_ext2_pager (); if (err) return err; get_hypermetadata (); map_hypermetadata (); resume_ext2_pager (); return 0; }
static int completion_try_print( int cols, wchar_t *prefix, int is_quoted, std::vector<comp_t *> &lst ) { /* The calculated preferred width of each column */ int pref_width[PAGER_MAX_COLS]; /* The calculated minimum width of each column */ int min_width[PAGER_MAX_COLS]; /* If the list can be printed with this width, width will contain the width of each column */ int *width=pref_width; /* Set to one if the list should be printed at this width */ int print=0; long i, j; int rows = (int)((lst.size()-1)/cols+1); int pref_tot_width=0; int min_tot_width = 0; int res=PAGER_RETRY; /* Skip completions on tiny terminals */ if( termsize.ws_col < PAGER_MIN_WIDTH ) return PAGER_DONE; memset( pref_width, 0, sizeof(pref_width) ); memset( min_width, 0, sizeof(min_width) ); /* Calculate how wide the list would be */ for( j = 0; j < cols; j++ ) { for( i = 0; i<rows; i++ ) { int pref,min; comp_t *c; if( lst.size() <= j*rows + i ) continue; c = lst.at(j*rows + i ); pref = c->pref_width; min = c->min_width; if( j != cols-1 ) { pref += 2; min += 2; } min_width[j] = maxi( min_width[j], min ); pref_width[j] = maxi( pref_width[j], pref ); } min_tot_width += min_width[j]; pref_tot_width += pref_width[j]; } /* Force fit if one column */ if( cols == 1) { if( pref_tot_width > termsize.ws_col ) { pref_width[0] = termsize.ws_col; } width = pref_width; print=1; } else if( pref_tot_width <= termsize.ws_col ) { /* Terminal is wide enough. Print the list! */ width = pref_width; print=1; } else { long next_rows = (lst.size()-1)/(cols-1)+1; /* fwprintf( stderr, L"cols %d, min_tot %d, term %d, rows=%d, nextrows %d, termrows %d, diff %d\n", cols, min_tot_width, termsize.ws_col, rows, next_rows, termsize.ws_row, pref_tot_width-termsize.ws_col ); */ if( min_tot_width < termsize.ws_col && ( ( (rows < termsize.ws_row) && (next_rows >= termsize.ws_row ) ) || ( pref_tot_width-termsize.ws_col< 4 && cols < 3 ) ) ) { /* Terminal almost wide enough, or squeezing makes the whole list fit on-screen. This part of the code is really important. People hate having to scroll through the completion list. In cases where there are a huge number of completions, it can't be helped, but it is not uncommon for the completions to _almost_ fit on one screen. In those cases, it is almost always desirable to 'squeeze' the completions into a single page. If we are using N columns and can get everything to fit using squeezing, but everything would also fit using N-1 columns, don't try. */ int tot_width = min_tot_width; width = min_width; while( tot_width < termsize.ws_col ) { for( i=0; (i<cols) && ( tot_width < termsize.ws_col ); i++ ) { if( width[i] < pref_width[i] ) { width[i]++; tot_width++; } } } print=1; } } if( print ) { res=PAGER_DONE; if( rows < termsize.ws_row ) { /* List fits on screen. Print it and leave */ if( is_ca_mode ) { is_ca_mode = 0; writembs(exit_ca_mode); } completion_print( cols, width, 0, rows, prefix, is_quoted, lst); pager_flush(); } else { int npos, pos = 0; int do_loop = 1; /* Enter ca_mode, which means that the terminal content will be restored to the current state on exit. */ if( enter_ca_mode && exit_ca_mode ) { is_ca_mode=1; writembs(enter_ca_mode); } completion_print( cols, width, 0, termsize.ws_row-1, prefix, is_quoted, lst); /* List does not fit on screen. Print one screenfull and leave a scrollable interface */ while(do_loop) { set_color( rgb_color_t::black(), get_color(HIGHLIGHT_PAGER_PROGRESS) ); wcstring msg = format_string(_(L" %d to %d of %d"), pos, pos+termsize.ws_row-1, rows ); msg.append(L" \r" ); writestr(msg.c_str()); set_color( rgb_color_t::normal(), rgb_color_t::normal() ); pager_flush(); int c = readch(); switch( c ) { case LINE_UP: { if( pos > 0 ) { pos--; writembs(tparm( cursor_address, 0, 0)); writembs(scroll_reverse); completion_print( cols, width, pos, pos+1, prefix, is_quoted, lst ); writembs( tparm( cursor_address, termsize.ws_row-1, 0) ); writembs(clr_eol ); } break; } case LINE_DOWN: { if( pos <= (rows - termsize.ws_row ) ) { pos++; completion_print( cols, width, pos+termsize.ws_row-2, pos+termsize.ws_row-1, prefix, is_quoted, lst ); } break; } case PAGE_DOWN: { npos = mini( (int)(rows - termsize.ws_row+1), (int)(pos + termsize.ws_row-1) ); if( npos != pos ) { pos = npos; completion_print( cols, width, pos, pos+termsize.ws_row-1, prefix, is_quoted, lst ); } else { if( flash_screen ) writembs( flash_screen ); } break; } case PAGE_UP: { npos = maxi( 0, pos - termsize.ws_row+1 ); if( npos != pos ) { pos = npos; completion_print( cols, width, pos, pos+termsize.ws_row-1, prefix, is_quoted, lst ); } else { if( flash_screen ) writembs( flash_screen ); } break; } case R_NULL: { do_loop=0; res=PAGER_RESIZE; break; } default: { out_buff.push_back( c ); do_loop = 0; break; } } } writembs(clr_eol); } } return res; }
int main( int argc, char **argv ) { int i; int is_quoted=0; wcstring_list_t comp; wchar_t *prefix = 0; int mangle_descriptors = 0; int result_fd = -1; set_main_thread(); setup_fork_guards(); /* This initialization is made early, so that the other init code can use global_context for memory managment */ program_name = L"fish_pager"; wsetlocale( LC_ALL, L"" ); /* The call signature for fish_pager is a mess. Because we want to be able to upgrade fish without breaking running instances, we need to support all previous modes. Unfortunatly, the two previous ones are a mess. The third one is designed to be extensible, so hopefully it will be the last. */ if( argc > 1 && argv[1][0] == '-' ) { /* Third mode */ int completion_fd = -1; FILE *completion_file; while( 1 ) { static struct option long_options[] = { { "result-fd", required_argument, 0, 'r' } , { "completion-fd", required_argument, 0, 'c' } , { "prefix", required_argument, 0, 'p' } , { "is-quoted", no_argument, 0, 'q' } , { "help", no_argument, 0, 'h' } , { "version", no_argument, 0, 'v' } , { 0, 0, 0, 0 } } ; int opt_index = 0; int opt = getopt_long( argc, argv, GETOPT_STRING, long_options, &opt_index ); if( opt == -1 ) break; switch( opt ) { case 0: { break; } case 'r': { result_fd = get_fd( optarg ); break; } case 'c': { completion_fd = get_fd( optarg ); break; } case 'p': { prefix = str2wcs(optarg); break; } case 'h': { print_help( argv[0], 1 ); exit(0); } case 'v': { debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION ); exit( 0 ); } case 'q': { is_quoted = 1; } } } if( completion_fd == -1 || result_fd == -1 ) { debug( 0, _(L"Unspecified file descriptors") ); exit( 1 ); } if( (completion_file = fdopen( completion_fd, "r" ) ) ) { read_array( completion_file, comp ); fclose( completion_file ); } else { debug( 0, _(L"Could not read completions") ); wperror( L"fdopen" ); exit( 1 ); } if( !prefix ) { prefix = wcsdup( L"" ); } } else { /* Second or first mode. These suck, but we need to support them for backwards compatibility. At least for some time. Third mode was implemented in January 2007, and previous modes should be considered deprecated from that point forward. A reasonable time frame for removal of the code below has yet to be determined. */ if( argc < 3 ) { print_help( argv[0], 1 ); exit( 0 ); } else { mangle_descriptors = 1; prefix = str2wcs( argv[2] ); is_quoted = strcmp( "1", argv[1] )==0; if( argc > 3 ) { /* First mode */ for( i=3; i<argc; i++ ) { wcstring wcs = str2wcstring( argv[i] ); comp.push_back(wcs); } } else { /* Second mode */ read_array( stdin, comp ); } } } // debug( 3, L"prefix is '%ls'", prefix ); init( mangle_descriptors, result_fd ); mangle_descriptions( comp ); if( wcscmp( prefix, L"-" ) == 0 ) join_completions( comp ); std::vector<comp_t *> completions = mangle_completions( comp, prefix ); /** Try to print the completions. Start by trying to print the list in PAGER_MAX_COLS columns, if the completions won't fit, reduce the number of columns by one. Printing a single column never fails. */ for( i = PAGER_MAX_COLS; i>0; i-- ) { switch( completion_try_print( i, prefix, is_quoted, completions ) ) { case PAGER_RETRY: break; case PAGER_DONE: i=0; break; case PAGER_RESIZE: /* This means we got a resize event, so we start over from the beginning. Since it the screen got bigger, we might be able to fit all completions on-screen. */ i=PAGER_MAX_COLS+1; break; } } free(prefix ); fwprintf( out_file, L"%ls", out_buff.c_str() ); if( is_ca_mode ) { writembs(exit_ca_mode); pager_flush(); } destroy(); }