C/ncurses/pads - how to deal at the edges of a pad shown on stdscr with prefresh

223 views Asked by At

I am new to c coding and trying out this and that. Recently I stumbled over ncurses and am experimenting with it.

In Dan Gookin's "guide to programming with ncurses". I saw pads and their properties and functionality and now I want to archive the following:

I want to create a pad of a by far bigger size than the screen, respectively, an outcut of stdscr, so the screen shows parts of the pad. The advantage compared with other solutions is that I don't need to mess around with offsets. you can just call the function

prefresh(padname, y, x, min_y, min_x, max_y, max_y);

which refreshes the screen stdscr and shows a part of the before prepared pad content in a "cutout" from min_y,min_x to max_y,max_x. The offset to the upper left corner is y,x.

So later I want to move around the pad in both directions left-right and up-down. I filled a pad with some dummy data ("Eat my pants" and an incremented number) and moved it around with simple for-loops. It worked out smoothly, but I realized a flaw. At the edges of the pad the information is "cut" and I cannot find a solution to make the wrap. If the offset is negative, prefresh does just through ERR, and the screen stays empty, while if the offset is too big the left or the lower boundaries came into view. That is generally not a problem, but I want to archive a solution where I can get control over the content to make it become something like an edgeless object. So if moving the pad too the left the right side shall be moved into view while and vice versa. Same for up and down. So like a cylinder or a pseudo-ball in a game world.

Anybody an idea how to achieve that with a pad shown on the stdscr with ncurses in a C environment?

Here's my test file (the commented and the lower parts are for testing, respectively, only to check out how scrolling in subwindows works. You will see the lower boundary coming into view after pressing a few times any key.

#include <ncurses.h>

void draw_borders(WINDOW *screen); // some test on winndows only

int main(int argc, char *argv[]) {
   int parent_x, parent_y, new_x, new_y;
   int left_size = 10;  // bad name, means height of the lower windows
   initscr();
   noecho();
   curs_set(FALSE);

   // init color use and define two colorpairs
   start_color();
   init_pair(1,COLOR_WHITE,COLOR_BLUE);
   init_pair(2,COLOR_BLACK, COLOR_YELLOW);
   init_pair(3,COLOR_BLACK, COLOR_CYAN);

   // get our maximum window dimensions
   getmaxyx(stdscr, parent_y, parent_x);

   // set up initial windows
   // WINDOW *field = newwin(parent_y - left_size, parent_x, 0, 0);
   // but main screen will be stdscr showing an
   // outcut of a padn so init pad here bigger than a screen
   WINDOW *mainscreen;
   mainscreen = newpad(500,1000);
   if (mainscreen == NULL) {
       endwin();
       puts("Sorry, unable to allocate mainscreen");
       return 1;
   }
   addstr("Added the new pad. Filling.\n");

   // fill the pad
   for ( int i = 0 ; i < 500000 ; i++) {
       wprintw(mainscreen, " Eat my shorts %4d ", i);
   }
   addstr("Press key to update screen.\n");
   getch();

//    this is to checkout what happens if the right edge comes into view
//    for (int x = 1000-parent_x ; x < 1000-parent_x + 10; x++) {
//        prefresh(mainscreen, 0, x, 0 , 0, parent_y - left_size -1, parent_x-1);
//        // napms(100);
//        getch();
//    }

// lower edge coming into view
   for (int y = 0 ; y < 10 ; y++) {
       prefresh(mainscreen, 500 - parent_y + left_size + y,
                0, 0 , 0, parent_y - left_size -1, parent_x-1);
       // napms(100);
       getch();
   }

   // only to checkout how subwindows work
   WINDOW *left = newwin(left_size, parent_x/2, parent_y - left_size, 0);
   WINDOW *right = newwin(left_size, parent_x/2, parent_y - left_size, parent_x/2);
   WINDOW *subwindow;

   //assign color to windows
   //wbkgd(field,COLOR_PAIR(1));
   wbkgd(left,COLOR_PAIR(2));
   wbkgd(right,COLOR_PAIR(3));

   // draw our borders
   //draw_borders(field);
   draw_borders(left);
   draw_borders(right);

// simulate a loop
//    while(1) {
//        getmaxyx(stdscr, new_y, new_x);
//        if (new_y != parent_y || new_x != parent_x) {
//            parent_x = new_x;
//            parent_y = new_y;
//            wresize(field, new_y - left_size, new_x);
//            wresize(left, left_size, new_x/2);
//            wresize(right, left_size, new_x/2);
//
//            mvwin(left, new_y - left_size, 0);
//            mvwin(right, new_y - left_size, parent_x/2);
//
//
//
//            wclear(stdscr);
//            wclear(field);
//            wclear(left);
//            wclear(right);
//
//            draw_borders(field);
//            draw_borders(left);
//            draw_borders(right);
//
//        }

           // wresize(field,parent_y - left_size, parent_x);
           wresize(left, left_size, parent_x/2);
           wresize(right, left_size, parent_x/2);

           mvwin(left, parent_y - left_size, 0);
           mvwin(right, parent_y - left_size, parent_x/2);

           // wclear(stdscr);
           // wclear(field);
           wclear(left);
           wclear(right);

//            draw_borders(field);
//            draw_borders(left);
           draw_borders(right);


       // draw to our windows
       mvwprintw(left, 1, 1, "Left. ");
       mvwprintw(right, 1, 1, "Right");

       // refresh each window
       refresh();
//        wrefresh(field);
       wrefresh(left);
       wrefresh(right);

       subwindow = derwin(left, left_size-2, (parent_x/2)-2, 1, 1);
//      scroll newly setup subwindow or not
       scrollok(subwindow, TRUE);


       for (int i = 0 ; i < 20 ; i++) {
           waddstr(subwindow, "This is just some boring placeholder text. ");
           napms(100);
           wrefresh(subwindow);
       }

       for (int i = 0 ; i < 3 ; i++) {
           scroll(subwindow);
           napms(100);
           wrefresh(subwindow);
       }

       for (int i = 0 ; i < 1 ; i++) {
           wscrl(subwindow,-3);
           napms(100);
           wrefresh(subwindow);
       }

//    }
getch();
       // clean up
//        delwin(field);
       delwin(left);
       endwin();
return 0;
}

void draw_borders(WINDOW *screen) {

   int x, y, i; getmaxyx(screen, y, x);

   // 4 corners
   mvwprintw(screen, 0, 0, "+");
   mvwprintw(screen, y - 1, 0, "+");
   mvwprintw(screen, 0, x - 1, "+");
   mvwprintw(screen, y - 1, x - 1, "+");

   // sides
   for (i = 1; i < (y - 1); i++) {
       mvwprintw(screen, i, 0, "|");
       mvwprintw(screen, i, x - 1, "|");
   }

   // top and bottom
   for (i = 1; i < (x - 1); i++) {
       mvwprintw(screen, 0, i, "-");
       mvwprintw(screen, y - 1, i, "-");
   }
}

0

There are 0 answers