Przeczytałem stronę podręcznika window(3NCURSES), ale nie mogę w pełni zrozumieć, co faktycznie robi funkcja mvwin() i co dzieje się z jej podoknami.

Poniższy kod tworzy okno z tytułem "Okno" i obramowaniem, tworzy również podokno, które jest używane do drukowania pozycji y,x bez uszkodzenia obramowania okna nadrzędnego. Następnie przenosi okno nadrzędne do nowej lokalizacji, ale wynik nie jest taki, jakiego się spodziewałem:

  1. Po przesunięciu okna kontur obramowania okna + tekst nie są automatycznie usuwane w starej lokalizacji.

  2. Po przeniesieniu, zapisanie tekstu do podokna, wypisuje go w starej i nowej lokalizacji.

  3. Po przeniesieniu okno nadrzędne ma nowe współrzędne y,x, ale podokno nadal pokazuje stare współrzędne.

Nie mam dużego doświadczenia z ncurses i może czegoś mi brakuje, ale to zachowanie jest całkowicie nielogiczne. Jeśli muszę ręcznie wymazywać okna w starej lokalizacji i ręcznie przenosić wszystkie podokna, to w pierwszej kolejności neguje to korzyść z używania ncurses. Spodziewałem się, że ncurses automatycznie obsłuży te niskopoziomowe szczegóły.

Moje rozumienie podokien było takie, że służą one do podziału jednego dużego okna na mniejsze, nienakładające się obszary. Tak więc, gdy okno nadrzędne zostanie przesunięte lub odświeżone, wszystkie jego podokna powinny zostać automatycznie przesunięte lub odświeżone. Czy to jest poprawne?

#include <assert.h>
#include <ncurses.h>
#include <unistd.h>

int main()
{
    WINDOW *win, *swin;
    int lines, cols, y, x;

    initscr();
    keypad(stdscr, TRUE);
    noecho();

    // Create window
    lines = 10; cols  = 40;
    y = 5; x = 5;
    win = newwin(lines, cols, y, x);
    assert(win != NULL);

    // Create window border
    box(win, 0, 0);
    mvwprintw(win, 0, 2, " Window ");

    // Create subwindow
    swin = subwin(win, lines-2, cols-2, y+1, x+1);
    assert(swin != NULL);
    // Print window and subwindow y,x
    mvwprintw(swin, 0, 0, "win y,x=%d,%d  swin y,x=%d,%d\n",
        getbegy(win), getbegx(win), getbegy(swin), getbegx(swin));

    // Refresh
    wnoutrefresh(stdscr);
    wnoutrefresh(win);
    wnoutrefresh(swin);
    doupdate();

    sleep(2);

    // Move window
    y = 20; x = 40;
    mvwin(win, y, x);
    mvwprintw(swin, 0, 0, "win y,x=%d,%d  swin y,x=%d,%d\n",
        getbegy(win), getbegx(win), getbegy(swin), getbegx(swin));

    // Refresh
    wnoutrefresh(stdscr);
    wnoutrefresh(win);
    wnoutrefresh(swin);
    doupdate();

    wgetch(swin);

    endwin();
    return 0;
}
1
user8996961 23 listopad 2018, 14:06

1 odpowiedź

Najlepsza odpowiedź

Najwyraźniej nie: szybkie sprawdzenie w Solarisie 10 daje to samo zachowanie. Możesz znaleźć scenariusz, w którym ncurses przypadkowo się różni, ale to nie jest jeden z nich. Najczęściej zadawane pytania mówi o zgodności:

rozszerzenia (odstępstwa od curses SVr4) są dozwolone tylko wtedy, gdy nie modyfikują udokumentowanego/obserwowanego zachowania API.

strona podręcznika systemu Solaris nie jasne, ponieważ jedyna wzmianka o podoknach dotyczy przenoszenia ich:

Procedura mvwin() przesuwa okno tak, że lewy górny róg znajduje się na pozycji (x, y). Jeśli przeniesienie spowodowałoby, że okno zniknęłoby z ekranu, jest to błąd i okno nie zostanie przesunięte. Przenoszenie podokien jest dozwolone, ale należy ich unikać.

Solaris kod źródłowy opowiada historię: nie robi nic z podokienkami. Niektóre ponowne testy jakiś czas temu (początek 2006) w odpowiedzi na komentarz użytkownika na temat Różnice wskazywały, że ncurses niepoprawnie próbowało kopiować podokna. Ta część jest niedostępna (ponieważ jest to zbyt interesujące, aby po prostu usunąć). Ponieważ niewiele zostało do zrobienia mvwin, rzeczywisty kod jest dość podobny.

Opis mvwin w X/Open jest zbyt krótki i niejasne, aby mieć jakikolwiek użytek.

1
Thomas Dickey 24 listopad 2018, 04:08