gpt4 book ai didi

c - 即使将 scrollok 设置为 true,ncurses 窗口滚动也不起作用

转载 作者:太空宇宙 更新时间:2023-11-04 04:13:56 24 4
gpt4 key购买 nike

我正在用 C 语言编写一个 ncurses 文件管理器,其 UI 类似于 ranger 文件管理器。到目前为止,这是我的代码:

#include <stdio.h>
#include <dirent.h>
#include <curses.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>


/*
Creates a new window with dimensions `height` and `width` starting at `starty` and `startx`
*/
WINDOW *create_newwin(int height, int width, int starty, int startx)
{
WINDOW *local_win;

local_win = newwin(height, width, starty, startx);

return local_win;
}


/*
Returns number of files in `char* directory`
*/
int getNumberofFiles(char* directory)
{
int len=0;
DIR *pDir;
struct dirent *pDirent;

pDir = opendir (directory);
if (pDir == NULL) {
printf ("Cannot open directory '%s'\n", directory);
exit(0);
}

while ((pDirent = readdir(pDir)) != NULL) {
// Skip hidden files
if(pDirent->d_name[0] != '.' )
len++;
}
return len;
}


/*
Stores all the file names in `char* directory` to `char *target[]`
*/
void getFiles(char* directory, char* target[])
{
int i = 0;
DIR *pDir;
struct dirent *pDirent;

pDir = opendir (directory);
if (pDir == NULL) {
printf ("Cannot open directory '%s'\n", directory);
exit(0);
}

while ((pDirent = readdir(pDir)) != NULL) {
// Skip hidden files
if(pDirent->d_name[0] != '.')
target[i++] = strdup(pDirent->d_name);
}

closedir (pDir);
}


int main(int argc, char* argv[])
{
// To store number of files in directory
int len=0;
// Counter variable
int i = 0;
// Direcotry to be opened
char* dir;

// Get UID of user
uid_t uid = getuid();
// Get home directory of user from UID
struct passwd *info = getpwuid(uid);

// No Path is given in arguments
// Set Path as $HOME
if(argc == 1)
{
dir = info->pw_dir;
}

// Path is given in arguments
// Set Path as the argument
else if(argc == 2)
{
dir = argv[1];

// Relative Path Given
if(dir[0] != '/')
{
// Add path of $HOME before the Relative Path
char temp[250] = "";
strcat(temp,info->pw_dir);
strcat(temp,"/");
strcat(temp,dir);
dir = temp;
}
}
// Incorrect Useage
else
{
printf("Incorrect Useage\n");
exit(0);
}

// Get number of files in the home directory
len = getNumberofFiles(dir);

// ncurses initialization
initscr();
raw();
noecho();
curs_set(0);

// Shows current directory
WINDOW *current_win;
// Shows child directory preview
WINDOW *preview_win;
int startx, starty, midx, midy, maxx, maxy;

// Index of currently selected item in `char* directories`
int selection = 0;
char ch;
do
{
len = getNumberofFiles(dir);
char* directories[len];
getFiles(dir, directories);

getmaxyx(stdscr, maxy, maxx);

// Make the two windows side-by-side
current_win = create_newwin(maxy, maxx/2+3, 0, 0);
preview_win = create_newwin(maxy, maxx/2 -1, 0, maxx/2 + 1);

// Print all the elements and highlight the selection
for( i=0; i<len; i++ )
{
if(i==selection)
wattron(current_win, A_STANDOUT);
else
wattroff(current_win, A_STANDOUT);
wmove(current_win,i+1,2);
wprintw(current_win, "%s\n", directories[i]);
}

char* selected_file = directories[selection];
char next_dir[250] = "";
char prev_dir[250] = "";
char *p;

// Get path of parent directory
strcat(prev_dir, dir);
p = strrchr(dir,'/');
prev_dir[p-dir] = '\0';

// Parent directory is root
if(prev_dir[0] != '/')
prev_dir[0] = '/';

// Get path of child directory
strcat(next_dir, dir);
strcat(next_dir, "/");
strcat(next_dir, directories[selection]);
int len_preview = getNumberofFiles(next_dir);
char* next_directories[len_preview];
getFiles(next_dir, next_directories);

for( i=0; i<len_preview; i++ )
{
wmove(preview_win,i+1,2);
wprintw(preview_win, "%s\n", next_directories[i]);
}

wattroff(current_win, A_STANDOUT);
box(current_win,0,0);
box(preview_win,0,0);
wrefresh(current_win);
wrefresh(preview_win);

// Keybindings
switch( ch = getch() ) {
case 'k':
selection--;
selection = ( selection < 0 ) ? len-1 : selection;
break;
case 'j':
selection++;
selection = ( selection > len-1 ) ? 0 : selection;
break;
case 'l':
strcpy(dir, next_dir);
selection = 0;
break;
case 'h':
strcpy(dir, prev_dir);
selection = 0;
break;
case 'g':
selection = 0;
break;
case 'G':
selection = len-1;
break;
}

// Free Memory
for( i=0; i<len_preview; i++ )
{
free(next_directories[i]);
}

for( i=0; i<len; i++ )
{
free(directories[i]);
}
} while( ch != 'q');

endwin();


return 0;
}

基本上,有两个并排呈现的窗口。一个是 current_win 显示当前目录中的所有文件,另一个是 preview_win 显示所选目录的子目录中的所有文件。

The problem is, when the present directory has a lot of files, the windows doesn't scrolls when the selection goes outside the window.我试过scrollok(current_win, TRUE); 但它会自动滚动到右下角并保持原样。

如何让它发挥作用?

(同样出于某种原因,在按下某个键之前,打开编译后的二进制文件后 shell 保持空白)

最佳答案

使用 scrollok 在窗口中滚动非常简单。当您写到末尾时,它会在底部插入一个空行。就是这样。顶部的那条线消失了?它消失了。不保存在一些屏幕外缓冲区中。一去不复返。这不是某种交互式的双向滚动。它不知道您的“选择”在哪里,也无法对这些信息做任何事情。

要进行反向滚动,您可以使用wscrl。像向前滚动一样,它只是添加一个空行(在顶部)。您有责任重新绘制属于该行的信息。

使用稍微高级一点的界面可能更容易,curses pad .

创建一个足够大的 pad 来容纳完整列表,并使用 prefresh 绘制顶部。 When the selection moves out of the visible area, call prefresh again with updated coordinates to tell it to show a portion of the pad that includes the new selection.

关于c - 即使将 scrollok 设置为 true,ncurses 窗口滚动也不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53979764/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com