ncursesw causing weird behaviour - c++

On WSL2, I'm using the first example code given in this tutorial website: https://tldp.org/HOWTO/NCURSES-Programming-HOWTO/panels.html.
Code:
#include <panel.h>
int main()
{ WINDOW *my_wins[3];
PANEL *my_panels[3];
int lines = 10, cols = 40, y = 2, x = 4, i;
initscr();
cbreak();
noecho();
/* Create windows for the panels */
my_wins[0] = newwin(lines, cols, y, x);
my_wins[1] = newwin(lines, cols, y + 1, x + 5);
my_wins[2] = newwin(lines, cols, y + 2, x + 10);
/*
* Create borders around the windows so that you can see the effect
* of panels
*/
for(i = 0; i < 3; ++i)
box(my_wins[i], 0, 0);
/* Attach a panel to each window */ /* Order is bottom up */
my_panels[0] = new_panel(my_wins[0]); /* Push 0, order: stdscr-0 */
my_panels[1] = new_panel(my_wins[1]); /* Push 1, order: stdscr-0-1 */
my_panels[2] = new_panel(my_wins[2]); /* Push 2, order: stdscr-0-1-2 */
/* Update the stacking order. 2nd panel will be on top */
update_panels();
/* Show it on the screen */
doupdate();
getch();
endwin();
}
When I run the code with the flags -lpanel -ncurses, it works fine as shown below:
When I run the code with the flags -lpanel -ncursesw, it doesn't work well:

The example shows two problems:
mixing -lpanel with -lncursesw (won't work because the size of the types holding character plus attributes differs).
You should use -lpanelw.
there's no call to setlocale to make line-drawing work portably.

Related

How to colorize console background with COLOREF RGB code?

Here I ask you : How are we supposed to colorize the console background with only the COLOREF datatype as a parameter?
The most common way of colorizing background is by using windows header function system("color --")
However, this way is not possible, and I am tasked to find out if we can colorize the console background using only the COLOREF datatype.
I did some research, and what I came across was SetConsoleAttribute(), and the windows header function system("color --").
This is what I expect my code to be:
COLOREF data = RGB(255, 0, 0);//red, basically
SetConsoleBackground(HDC *console, data);
Any way of doing this? Thanks in advance.
[NEW ANSWER (edit)]
So #IInspectable pointed out the the console now supports 24-bit full rgb colors so i did some research and managed to make it work.
This is how i solved it:
#include <Windows.h>
#include <string>
struct Color
{
int r;
int g;
int b;
};
void SetBackgroundColor(const Color& aColor)
{
std::string modifier = "\x1b[48;2;" + std::to_string(aColor.r) + ";" + std::to_string(aColor.g) + ";" + std::to_string(aColor.b) + "m";
printf(modifier.c_str());
}
void SetForegroundColor(const Color& aColor)
{
std::string modifier = "\x1b[38;2;" + std::to_string(aColor.r) + ";" + std::to_string(aColor.g) + ";" + std::to_string(aColor.b) + "m";
printf(modifier.c_str());
}
int main()
{
// Set output mode to handle virtual terminal sequences
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD dwMode = 0;
GetConsoleMode(hOut, &dwMode);
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hOut, dwMode);
SetForegroundColor({ 100,100,20 });
SetBackgroundColor({ 50,100,10 });
printf("Hello World\n");
system("pause");
}
[OLD ANSWER]
The console only supports 256 different color combinations defined with a WORD which is 8 bits long. The background color is stored in the 4 higher bits. This means the console only has support for 16 different colors:
enum class Color : int
{
Black = 0,
DarkBlue = 1,
DarkGreen = 2,
DarkCyan = 3,
DarkRed = 4,
DarkPurple = 5,
DarkYellow = 6,
DarkWhite = 7,
Gray = 8,
Blue = 9,
Green = 10,
Cyan = 11,
Red = 12,
Purple = 13,
Yellow = 14,
White = 15,
};
To set the background color of the typed characters, you could do:
void SetWriteColor(const Color& aColor)
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, static_cast<WORD>(aColor) << 4);
}

C++ - swprintf_s doesn't output to buffer in console

I'm writing a console game in C++ and I'd like to be able to do menus easily. The screen state is stored in a wchar_t* screen[screenWidth*screenHeight]. I wrote a class Menu that should write to my screenbuffer to display a scoreboard. The class has a draw function that takes a pointer to the screenbuffer and some coordinate parameters. The draw function uses swprintf_s to change the state of the screenbuffer, however when I run the code it doesn't output anything. I tried changing the swprintf_s call by passing in a literal but it still doesn't work. However when I just use raw swprintf_s from main() it works.
void Menu::draw(wchar_t* screen, int xScreen, int yScreen, int xField, int yField,
int xMenu, int yMenu) {
for (int i = 0; i < buttons.size(); ++i) {
int currentY = yMenu / (buttons.size() + 1) * (i + 1);
swprintf_s(&screen[xScreen * currentY + xField + xMenu / 2 - 7], 16, buttons[i].str);
}
}
buttons is a vector of menus, str is a wchar_t* to the menu's text.
When I just use the function in main:swprintf_s(&screen[15 * nScreenWidth + nFieldWidth + 6], 16, L"SCORE: %8d", nScore);
outputs as it should. Any suggestions?

How are pixels arranged in SDL2?

I have 2x2 image
Shouldn't the pixels be arranged like this?
1 2 // each number is a pixel
3 4
I'm having trouble accessing a pixel with x and y because
when x = 1 and y = 0 i get index 2 but prints the rgb values of pixel 4
so it's something like?
1 2 // each number is a pixel
4 3
Here's the code that I use
index = y + x * s->w;
c = s->format->palette->colors[index]; // c is an SDL_Color and s is an SDL_Surface*
I also use this for loop and still prints the same
for (Uint8 i = *(Uint8 *)s->pixels; i < s->w*s->h; i++) {
c = s->format->palette->colors[i];
printf("%u %u %u %u \n", i, c.r , c.g , c.b);
}
SDL_Surface struct definition from the SDL documentation
typedef struct SDL_Surface {
Uint32 flags; /* Read-only */
SDL_PixelFormat *format; /* Read-only */
int w, h; /* Read-only */
Uint16 pitch; /* Read-only */
void *pixels; /* Read-write */
/* clipping information */
SDL_Rect clip_rect; /* Read-only */
/* Reference count -- used when freeing surface */
int refcount; /* Read-mostly */
/* This structure also contains private fields not shown here */
} SDL_Surface;
Uint8 *pixel = (Uint8 *)s->pixels,*index;
index = &pixel[y + x * s->pitch];
c = s->format->palette->colors[*index];
Got it doing using #holyblackcat's suggestion.

Outputs in console with WriteConsoleOutputA

Hi I'm trying to make an output with WriteConsoleOutputA.
I have this code:
CHAR_INFO letterA;
letterA.Char.AsciiChar = 'A';
letterA.Attributes =
FOREGROUND_RED | FOREGROUND_INTENSITY |
BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
//Set up the positions:
COORD charBufSize = { 1, 1};
COORD characterPos = { 0, 0 };
SMALL_RECT writeArea = { 0,0,0,0 };
//Write the character
WriteConsoleOutputA(wHnd, &letterA, charBufSize, characterPos, &writeArea);
So at this point it writes a red A with a yellow background, but for example, if I want the A appear in the coordinates (5,5) it doesn't print it even if I change SMALL_RECT to {0, 0, 10, 10}.
Or if I want to write another A right side to the first one with this:
WriteConsoleOutputA(wHnd, &letterA, charBufSize, characterPos, &writeArea);
WriteConsoleOutputA(wHnd, &letterA, charBufSize, { 0, 1 }, &writeArea);
I´m beginning with this graphical console mode, it would be very helpful if someone could tell me how to print that character in the coordinate that I want.
I have tried to change it , changing the coordinates something like this:
COORD charBufSize = { 5, 10};
COORD characterPos = { 3, 2 };
SMALL_RECT writeArea = { 0,0,5,10 };
but it prints weird characters and other colours in all the buffer 5*10.
Thanks
César.
WriteConsoleOutput(..) is a complex function which needs to be handled carefully.
The dwBufferSize parameter (= your charBufSize) is nothing more than a size specification of the lpBuffer parameter (= your letterA). The only difference instead of simply telling that letterA has a size of 1 is that by splitting it into two axis you are able specify the width and height of a text block with letterA characters in it. But remember that the size of letterA has to be charBufSize.X * charBufSize.Y. Otherwise WriteConsoleOutput will do weird stuff since it uses uninitialized memory.
The dwBufferCoord parameter (= your characterPos) defines the location within letterA from where to read the characters to be written to the console. So it simply defines an index offset. In your example this should always be { 0, 0 } (which is equal to letterA[0]) since letterA is only a single character.
The lpWriteRegion parameter (= your writeArea) does all the magic. It specifies the position, width and height of the area to be written by the call. The data to be written is definedby the previous parameters.
So to write a character to a specific location x, y do the following:
COORD charBufSize = {1, 1};
COORD characterPos = {0, 0};
SMALL_RECT writeArea = {x, y, x, y};
WriteConsoleOutputA(wHnd, &letterA, charBufSize, characterPos, &writeArea);
For a little better understanding use the following example and play a little with the values of charBufSize, characterPos and writeArea:
int i;
CHAR_INFO charInfo[10 * 10];
/* play with these values */
COORD charBufSize = {10, 10}; /* do not exceed x*y=100 !!! */
COORD characterPos = {5, 0}; /* must be within 0 and x*y=100 */
SMALL_RECT writeArea = {2, 2, 12, 12};
for (i = 0; i < (10 * 10); i++)
{
charInfo[i].Char.AsciiChar = 'A' + (i % 26);
charInfo[i].Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
}
WriteConsoleOutputA(wHnd, charInfo, charBufSize, characterPos, &writeArea);
Here is a screenshot of the parameters in the example above showing the console and the variables. I hope this makes it a bit more clear.

Using GLPK in parallel_for loop

I want to run the LP solver in GLPK in a parallel_for loop. The problems are all independent of each other so there shouldn't be any interference.
Here is an example code that fails, this is essentially the example code from the glpk wikibook but wrapped in a parallel_for loop. Any help will be appreciated
//#include <stdio.h> /* C input/output */
//#include <stdlib.h> /* C standard library */
#include <iostream>
#include <glpk.h> /* GNU GLPK linear/mixed integer solver */
#include <ppl.h>
using namespace concurrency;
using namespace std;
void main()
{
parallel_for(0, 10, [](int i){
/* declare variables */
glp_prob *lp;
int *ia = new int[4];
int *ja = new int[4];
double *ar = new double[4];
double z, x1, x2;
/* create problem */
lp = glp_create_prob();
glp_set_prob_name(lp, "minimax");
glp_set_obj_dir(lp, GLP_MAX);
/* fill problem */
glp_add_rows(lp, 2);
//glp_set_row_name(lp, 1, "p");
glp_set_row_bnds(lp, 1, GLP_UP, 0.0, 1.0);
//glp_set_row_name(lp, 2, "q");
glp_set_row_bnds(lp, 2, GLP_UP, 0.0, 2.0);
glp_add_cols(lp, 2);
//glp_set_col_name(lp, 1, "x1");
glp_set_col_bnds(lp, 1, GLP_LO, 0.0, 0.0);
glp_set_obj_coef(lp, 1, 0.6);
//glp_set_col_name(lp, 2, "x2");
glp_set_col_bnds(lp, 2, GLP_LO, 0.0, 0.0);
glp_set_obj_coef(lp, 2, 0.5);
ia[1] = 1, ja[1] = 1, ar[1] = 1.0; /* a[1,1] = 1 */
ia[2] = 1, ja[2] = 2, ar[2] = 2.0; /* a[1,2] = 2 */
ia[3] = 2, ja[3] = 1, ar[3] = 3.0; /* a[2,1] = 3 */
ia[4] = 2, ja[4] = 2, ar[4] = 1.0; /* a[2,2] = 1 */
glp_load_matrix(lp, 4, ia, ja, ar);
/* solve problem */
glp_simplex(lp, NULL);
/* recover and display results */
z = glp_get_obj_val(lp);
x1 = glp_get_col_prim(lp, 1);
x2 = glp_get_col_prim(lp, 2);
printf("z = %g; x1 = %g; x2 = %g\n", z, x1, x2);
/* housekeeping */
glp_delete_prob(lp);
glp_free_env();
});
system("pause");
}
You're calling glp_free_env from inside each thread, while the library is still actively doing work in other threads. That won't work well -- you're yanking the rug out from under threads working hard..
Instead call it only after all threads completed computation (join them). For this simple example, you can probably skip the cleanup step altogether.
I have found the problem. The issue is with the GLPK source code, there are a couple of routines that are not reenterable causing some big issues. This is documented here: http://en.wikibooks.org/wiki/GLPK/Using_the_GLPK_callable_library . There is also a fix in place but it requires rebuilding it. Note that this only works with version 4.50 of GLPK and older, newer versions have a slightly different layout.
While Ben was completely correct, making this change to the library solves all issues and lets you free the environment inside the loop.