Я разрабатываю графическую библиотеку для создания 2D-графики на терминале. Мне нужно контролировать количество строк и столбцов, чтобы указать разрешение. Я хочу знать, есть ли возможность справиться с этим и сделать приложение переносимым на терминалы, чтобы мне не приходилось реализовывать opengl.
Я пробовал использовать эмуляторы терминала Gtk и Qt, но мне это не удалось.
Как открыть терминал? И, пожалуйста, придерживайтесь только одного языка.
Вы можете использовать мультиплатформенную библиотеку cairo
для 2D-графики. Разрешение области рисования и управление ею зависят от выбранной платформы (ее можно использовать непосредственно в бэкэндах X11/Xorg или, например, в рамках GTK).
Не знаю, достаточно ли это общее, но для xterm
это работает.
Это работает, потому что xterm
экспортирует свой идентификатор окна в среду как WINDOWID
.
Мы можем использовать это значение в вызовах XGetWindowAttributes
и XResizeWindow
.
Ширина/высота указывается в пикселях, а не в строках/столбцах символов.
Если в окне есть полосы прокрутки и т. д. Я не знаю, включает ли их геометрия или нет.
Если геометрия не делится на используемую ширину/высоту шрифта, xterm
будет корректироваться так, чтобы разрешать только ширину/высоту, кратную ширине/высоте шрифта (хорошая вещь).
xterm
настроит геометрию через termios
, так что подпрограмма сможет получить геометрию персонажа через tcgetattr
Цвета переднего плана и фона можно изменить с помощью escape-кодов, отправленных на stdout
.
Однако, AFAICT, сложно определить или изменить шрифт. Или украшение окон.
Примечание: возможно, есть способы получше, но...
Мне удалось изменить геометрию xterm
, используя следующее. Обратите внимание, что это всего лишь демонстрация, в которой нет проверки ошибок:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <X11/Xlib.h>
int
main(int argc,char **argv)
{
--argc;
++argv;
Display *dpy = XOpenDisplay(NULL);
char *cp = getenv("WINDOWID");
if (cp == NULL) {
printf("No WINDOWID\n");
exit(1);
}
long xid = atoll(cp);
printf("xid=%ld\n",xid);
XWindowAttributes attr;
XGetWindowAttributes(dpy,xid,&attr);
printf("OLD: width=%d height=%d\n",attr.width,attr.height);
int termfd = 1;
struct winsize ws;
ioctl(termfd,TIOCGWINSZ,&ws);
printf("CHAR: rows=%d cols=%d\n",ws.ws_row,ws.ws_col);
int wid = -1;
int hgt = -1;
if (argc > 0) {
wid = atoi(*argv++);
--argc;
}
if (argc > 0) {
hgt = atoi(*argv++);
--argc;
}
printf("ARG: width=%d height=%d\n",wid,hgt);
int chg = (wid > 0) || (hgt > 0);
if (wid < 0)
wid = attr.width;
if (hgt < 0)
hgt = attr.height;
if (chg) {
printf("CHG: width=%d height=%d\n",wid,hgt);
XResizeWindow(dpy,xid,wid,hgt);
//XFlush(dpy);
XSync(dpy,0);
}
// a hack: give xterm time to change window character size
struct winsize ws2;
for (int iter = 1; iter <= 10000; ++iter) {
ioctl(termfd,TIOCGWINSZ,&ws2);
if (! chg)
break;
if (ws2.ws_row != ws.ws_row)
break;
if (ws2.ws_col != ws.ws_col)
break;
}
XGetWindowAttributes(dpy,xid,&attr);
printf("NEW: width=%d height=%d\n",attr.width,attr.height);
printf("CHAR: rows=%d cols=%d\n",ws2.ws_row,ws2.ws_col);
XCloseDisplay(dpy);
return 0;
}
Возможно, было бы проще вызвать xterm
как подпрограмму (и запустить в ней целевую программу):
xterm [options] -e myprogram
xterm
имеет множество параметров командной строки для управления геометрией символов, шрифтом, полосами прокрутки, украшениями, цветами и т. д.
Если вам нужен переносимый код для управления терминалом, вам следует посмотреть библиотеку ncurses.