mirror of
https://github.com/tuxbox-fork-migrations/recycled-ni-neutrino.git
synced 2025-08-28 16:01:10 +02:00
Merge branch 'pu/fb-setmode' of https://github.com/tuxbox-neutrino/gui-neutrino into ni/tuxbox
Conflicts:
lib/libtuxtxt/tuxtxt.cpp
lib/libtuxtxt/tuxtxt.h
src/driver/fb_generic.h
Origin commit data
------------------
Branch: ni/coolstream
Commit: 3ff64707df
Author: vanhofen <vanhofen@gmx.de>
Date: 2017-02-15 (Wed, 15 Feb 2017)
------------------
This commit was generated by Migit
This commit is contained in:
@@ -11,6 +11,8 @@
|
||||
* *
|
||||
* ported 2009 to HD1 by Coolstream LTD *
|
||||
* *
|
||||
* TD, SPARK and AZbox port (C) 2010-2013 Stefan Seyfried *
|
||||
* *
|
||||
******************************************************************************/
|
||||
|
||||
#include "teletext.h"
|
||||
@@ -19,6 +21,7 @@
|
||||
#include <dmx.h>
|
||||
#include <video.h>
|
||||
#include <sys/stat.h>
|
||||
#include <global.h>
|
||||
#include <system/set_threadname.h>
|
||||
|
||||
/* same as in rcinput.h... */
|
||||
@@ -26,6 +29,12 @@
|
||||
#define KEY_TTZOOM KEY_FN_2
|
||||
#define KEY_REVEAL KEY_FN_D
|
||||
|
||||
#ifdef HAVE_SPARK_HARDWARE
|
||||
#define MARK_FB(a, b, c, d) if (p == lfb) CFrameBuffer::getInstance()->mark(a, b, (a) + (c), (b) + (d))
|
||||
#else
|
||||
#define MARK_FB(a, b, c, d)
|
||||
#endif
|
||||
|
||||
extern cVideo * videoDecoder;
|
||||
|
||||
static pthread_t ttx_sub_thread;
|
||||
@@ -36,25 +45,34 @@ static int sub_pid, sub_page;
|
||||
static bool use_gui;
|
||||
static int cfg_national_subset;
|
||||
|
||||
static int screen_x, screen_y, screen_w, screen_h;
|
||||
|
||||
//#define USE_FBPAN // FBIOPAN_DISPLAY seems to be working in current driver
|
||||
|
||||
fb_pixel_t *getFBp(int *y)
|
||||
{
|
||||
if (*y < (int)var_screeninfo.yres)
|
||||
return lfb;
|
||||
|
||||
*y -= var_screeninfo.yres;
|
||||
return lbb;
|
||||
}
|
||||
|
||||
void FillRect(int x, int y, int w, int h, int color)
|
||||
{
|
||||
unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length;
|
||||
#if !HAVE_TRIPLEDRAGON
|
||||
unsigned int col = bgra[color][3] << 24 | bgra[color][2] << 16 | bgra[color][1] << 8 | bgra[color][0];
|
||||
#else
|
||||
unsigned int col = *((unsigned int*)bgra[color]);
|
||||
#endif
|
||||
fb_pixel_t *p = getFBp(&y);
|
||||
MARK_FB(x, y, w, h);
|
||||
p += x + y * stride;
|
||||
if (w > 0)
|
||||
for (int count = 0; count < h; count++) {
|
||||
unsigned int * dest0 = (unsigned int *)p;
|
||||
fb_pixel_t *dest0 = p;
|
||||
for (int i = 0; i < w; i++)
|
||||
*(dest0++) = col;
|
||||
p += fix_screeninfo.line_length;
|
||||
*(dest0++) = bgra[color];
|
||||
p += stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FillBorder(int color)
|
||||
{
|
||||
int ys = (var_screeninfo.yres-var_screeninfo.yoffset);
|
||||
@@ -180,7 +198,6 @@ int toptext_getnext(int startpage, int up, int findgroup)
|
||||
nextgrp = nextblk = 0;
|
||||
current = startpage;
|
||||
|
||||
//NI
|
||||
if (startpage == 0)
|
||||
return 0;
|
||||
|
||||
@@ -224,6 +241,13 @@ void RenderClearMenuLineBB(char *p, tstPageAttr *attrcol, tstPageAttr *attr)
|
||||
#if 0
|
||||
RenderCharBB(' ', attr); /* separator */
|
||||
#endif
|
||||
/* the fontwidth_topmenusmall is not correctly calculated: the navigation
|
||||
* indicator ' ' is not considered and thus the font is slightly too wide.
|
||||
* Shift the topmenu to the left instead of using a smaller font, since
|
||||
* the worst that can happen is that the indicator is partly obscured and
|
||||
* that looks better than empty space on the right of the topmenu.
|
||||
*/
|
||||
PosX = screen_x + screen_w - TOPMENUCHARS * fontwidth_topmenusmall;
|
||||
for(col = 0; col < TOPMENUCHARS; col++)
|
||||
{
|
||||
RenderCharBB(*p++, attr);
|
||||
@@ -246,7 +270,8 @@ void ClearFB(int /*color*/)
|
||||
//never used
|
||||
void ClearB(int color)
|
||||
{
|
||||
FillRect(0,0,var_screeninfo.xres,var_screeninfo.yres*2,color);
|
||||
FillRect(0, 0, var_screeninfo.xres, var_screeninfo.yres, color); /* framebuffer */
|
||||
FillRect(0, var_screeninfo.yres, var_screeninfo.xres, var_screeninfo.yres, color); /* backbuffer */
|
||||
}
|
||||
#endif
|
||||
int GetCurFontWidth()
|
||||
@@ -254,6 +279,7 @@ int GetCurFontWidth()
|
||||
int mx = (displaywidth)%(40-nofirst); // # of unused pixels
|
||||
int abx = (mx == 0 ? displaywidth+1 : (displaywidth)/(mx+1));// distance between 'inserted' pixels
|
||||
int nx= abx+1-((PosX-sx) % (abx+1)); // # of pixels to next insert
|
||||
|
||||
return fontwidth+(((PosX+fontwidth+1-sx) <= displaywidth && nx <= fontwidth+1) ? 1 : 0);
|
||||
}
|
||||
|
||||
@@ -288,25 +314,14 @@ void setfontwidth(int newwidth)
|
||||
}
|
||||
}
|
||||
|
||||
#if HAVE_TRIPLEDRAGON
|
||||
#define _A 0
|
||||
#define _R 1
|
||||
#define _G 2
|
||||
#define _B 3
|
||||
#else
|
||||
#define _A 3
|
||||
#define _R 2
|
||||
#define _G 1
|
||||
#define _B 0
|
||||
#endif
|
||||
void setcolors(unsigned short *pcolormap, int offset, int number)
|
||||
{
|
||||
int i,trans_tmp;
|
||||
int i,trans_tmp,tr;
|
||||
int j = offset; /* index in global color table */
|
||||
|
||||
trans_tmp=25-trans_mode;
|
||||
|
||||
bgra[transp2][_A]=((trans_tmp+7)<<11 | 0x7FF)>>8;
|
||||
int R = var_screeninfo.red.offset;
|
||||
int G = var_screeninfo.green.offset;
|
||||
int B = var_screeninfo.blue.offset;
|
||||
int A = var_screeninfo.transp.offset;
|
||||
|
||||
for (i = 0; i < number; i++)
|
||||
{
|
||||
@@ -317,13 +332,17 @@ void setcolors(unsigned short *pcolormap, int offset, int number)
|
||||
r = (r * (0x3f+(color_mode<<3))) >> 8;
|
||||
g = (g * (0x3f+(color_mode<<3))) >> 8;
|
||||
b = (b * (0x3f+(color_mode<<3))) >> 8;
|
||||
|
||||
bgra[j][_R]=r;
|
||||
bgra[j][_G]=g;
|
||||
bgra[j][_B]=b;
|
||||
|
||||
bgra[j] = (r << R) | (g << G) | (b << B) | (0xff << A);
|
||||
j++;
|
||||
}
|
||||
trans_tmp=25-trans_mode;
|
||||
tr = ((trans_tmp+7)<<11 | 0x7FF)>>8;
|
||||
bgra[transp2] &= ~(0xff << A); /* clear alpha */
|
||||
bgra[transp2] |= tr << A;
|
||||
bgra[menu3] &= ~(0xff << A);
|
||||
bgra[menu3] |= 0xc0 << A;
|
||||
bgra[transp] &= ~(0xff << A);
|
||||
bgra[transp] |= 0;
|
||||
}
|
||||
|
||||
/* hexdump of page contents to stdout for debugging */
|
||||
@@ -1539,7 +1558,7 @@ static void* reader_thread(void * /*arg*/)
|
||||
void tuxtx_pause_subtitle(bool pause)
|
||||
{
|
||||
if(!pause) {
|
||||
printf("TuxTxt subtitle unpause, running %d pid %d page %d\n", reader_running, sub_pid, sub_page);
|
||||
//printf("TuxTxt subtitle unpause, running %d pid %d page %d\n", reader_running, sub_pid, sub_page);
|
||||
ttx_paused = 0;
|
||||
if(!reader_running && sub_pid && sub_page)
|
||||
tuxtx_main(0, sub_pid, sub_page);
|
||||
@@ -1576,8 +1595,8 @@ void tuxtx_set_pid(int pid, int page, const char * cc)
|
||||
sub_page = page;
|
||||
|
||||
cfg_national_subset = GetNationalSubset(cc);
|
||||
printf("TuxTxt subtitle set pid %d page %d lang %s (%d)\n", sub_pid, sub_page, cc, cfg_national_subset);
|
||||
#if 0
|
||||
printf("TuxTxt subtitle set pid %d page %d lang %s (%d)\n", sub_pid, sub_page, cc, cfg_national_subset);
|
||||
ttx_paused = 1;
|
||||
if(sub_pid && sub_page)
|
||||
tuxtx_main(0, sub_pid, sub_page);
|
||||
@@ -1601,7 +1620,7 @@ int tuxtx_subtitle_running(int *pid, int *page, int *running)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tuxtx_main(int _rc, int pid, int page, int source)
|
||||
int tuxtx_main(int /*_rc*/, int pid, int page, int source)
|
||||
{
|
||||
char cvs_revision[] = "$Revision: 1.95 $";
|
||||
|
||||
@@ -1625,14 +1644,18 @@ int tuxtx_main(int _rc, int pid, int page, int source)
|
||||
printf("TuxTxt %s\n", versioninfo);
|
||||
printf("for 32bpp framebuffer\n");
|
||||
|
||||
fb = -1;
|
||||
#ifdef USE_FBPAN
|
||||
if ((fb=open("/dev/fb/0", O_RDWR)) == -1)
|
||||
{
|
||||
perror("TuxTxt <open /dev/fb/0>");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = _rc;
|
||||
lfb = (unsigned char *) CFrameBuffer::getInstance()->getFrameBufferPointer();
|
||||
CFrameBuffer *fbp = CFrameBuffer::getInstance();
|
||||
lfb = fbp->getFrameBufferPointer();
|
||||
lbb = fbp->getBackBufferPointer();
|
||||
|
||||
tuxtxt_cache.vtxtpid = pid;
|
||||
|
||||
@@ -1641,8 +1664,7 @@ int tuxtx_main(int _rc, int pid, int page, int source)
|
||||
else
|
||||
printf("[tuxtxt] using PID %x page %d\n", tuxtxt_cache.vtxtpid, tuxtxt_cache.page);
|
||||
|
||||
fcntl(rc, F_SETFL, fcntl(rc, F_GETFL) | O_EXCL | O_NONBLOCK);
|
||||
|
||||
#if 0 /* just get it from the framebuffer class */
|
||||
/* get fixed screeninfo */
|
||||
if (ioctl(fb, FBIOGET_FSCREENINFO, &fix_screeninfo) == -1)
|
||||
{
|
||||
@@ -1656,7 +1678,14 @@ int tuxtx_main(int _rc, int pid, int page, int source)
|
||||
perror("TuxTxt <FBIOGET_VSCREENINFO>");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
struct fb_var_screeninfo *var;
|
||||
var = fbp->getScreenInfo();
|
||||
/* this is actually the length of the screen in pixels */
|
||||
stride = fbp->getStride() / sizeof(fb_pixel_t);
|
||||
memcpy(&var_screeninfo, var, sizeof(struct fb_var_screeninfo));
|
||||
fix_screeninfo.line_length = var_screeninfo.xres * sizeof(fb_pixel_t);
|
||||
#endif
|
||||
/* set variable screeninfo for double buffering */
|
||||
var_screeninfo.yoffset = 0;
|
||||
#if 0
|
||||
@@ -1665,10 +1694,15 @@ int tuxtx_main(int _rc, int pid, int page, int source)
|
||||
ex = x + w - 10;
|
||||
ey = y + h - 10;
|
||||
#endif
|
||||
int x = CFrameBuffer::getInstance()->getScreenX();
|
||||
int y = CFrameBuffer::getInstance()->getScreenY();
|
||||
int w = CFrameBuffer::getInstance()->getScreenWidth();
|
||||
int h = CFrameBuffer::getInstance()->getScreenHeight();
|
||||
screen_x = fbp->getScreenX();
|
||||
screen_y = fbp->getScreenY();
|
||||
screen_w = fbp->getScreenWidth();
|
||||
screen_h = fbp->getScreenHeight();
|
||||
|
||||
int x = screen_x;
|
||||
int y = screen_y;
|
||||
int w = screen_w;
|
||||
int h = screen_h;
|
||||
|
||||
int tx = 0;
|
||||
if (!screen_mode1)
|
||||
@@ -1729,6 +1763,7 @@ int tuxtx_main(int _rc, int pid, int page, int source)
|
||||
SwitchTranspMode();
|
||||
break; /* and evaluate key */
|
||||
|
||||
case RC_TTTV:
|
||||
case RC_MUTE: /* regular toggle to transparent */
|
||||
case RC_TEXT:
|
||||
break;
|
||||
@@ -1801,20 +1836,25 @@ int tuxtx_main(int _rc, int pid, int page, int source)
|
||||
case RC_7:
|
||||
case RC_8:
|
||||
case RC_9:
|
||||
PageInput(RCCode - RC_0);
|
||||
PageInput(CRCInput::getNumericValue(RCCode));
|
||||
break;
|
||||
case RC_RED: ColorKey(prev_100); break;
|
||||
case RC_GREEN: ColorKey(prev_10); break;
|
||||
case RC_YELLOW: ColorKey(next_10); break;
|
||||
case RC_BLUE: ColorKey(next_100); break;
|
||||
case RC_TTZOOM:
|
||||
case RC_PLUS: SwitchZoomMode(); break;
|
||||
case RC_SPLIT:
|
||||
case RC_MINUS: SwitchScreenMode(-1);prevscreenmode = screenmode; break;
|
||||
case RC_TTTV:
|
||||
case RC_MUTE: SwitchTranspMode(); break;
|
||||
case RC_TEXT:
|
||||
if(transpmode == 1)
|
||||
RCCode = RC_HOME;
|
||||
SwitchTranspMode();
|
||||
break;
|
||||
case RC_TTREVEAL:
|
||||
case RC_INFO:
|
||||
case RC_HELP: SwitchHintMode(); break;
|
||||
case RC_DBOX: ConfigMenu(0); break;
|
||||
case RC_HOME:
|
||||
@@ -1831,7 +1871,8 @@ int tuxtx_main(int _rc, int pid, int page, int source)
|
||||
/* exit */
|
||||
CleanUp();
|
||||
|
||||
close(fb);
|
||||
if (fb >= 0)
|
||||
close(fb);
|
||||
|
||||
#if 1
|
||||
if ( initialized )
|
||||
@@ -1867,10 +1908,10 @@ FT_Error MyFaceRequester(FTC_FaceID face_id, FT_Library plibrary, FT_Pointer /*r
|
||||
******************************************************************************/
|
||||
extern std::string ttx_font_file;
|
||||
static bool ft_init_done = false;
|
||||
static int oldfontheight = 0;
|
||||
int Init(int source)
|
||||
{
|
||||
int error, i;
|
||||
unsigned char magazine;
|
||||
static std::string font_file;
|
||||
|
||||
/* init data */
|
||||
@@ -1878,12 +1919,13 @@ int Init(int source)
|
||||
//page_atrb[32] = transp<<4 | transp;
|
||||
inputcounter = 2;
|
||||
|
||||
#if TUXTXT_CFG_STANDALONE
|
||||
unsigned char magazine;
|
||||
for (magazine = 1; magazine < 9; magazine++)
|
||||
{
|
||||
tuxtxt_cache.current_page [magazine] = -1;
|
||||
tuxtxt_cache.current_subpage [magazine] = -1;
|
||||
}
|
||||
#if TUXTXT_CFG_STANDALONE
|
||||
/* init data */
|
||||
memset(&tuxtxt_cache.astCachetable, 0, sizeof(tuxtxt_cache.astCachetable));
|
||||
memset(&tuxtxt_cache.subpagetable, 0xFF, sizeof(tuxtxt_cache.subpagetable));
|
||||
@@ -2033,7 +2075,7 @@ int Init(int source)
|
||||
fontwidth_topmenumain = (TV43STARTX-sx) / 40;
|
||||
fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS;
|
||||
//fontwidth_small = (TV169FULLSTARTX-sx) / 40;
|
||||
fontwidth_small = (CFrameBuffer::getInstance()->getScreenWidth()/2) / 40;
|
||||
fontwidth_small = (screen_w / 2) / 40;
|
||||
ymosaic[0] = 0; /* y-offsets for 2*3 mosaic */
|
||||
ymosaic[1] = (fontheight + 1) / 3;
|
||||
ymosaic[2] = (fontheight * 2 + 1) / 3;
|
||||
@@ -2075,7 +2117,7 @@ int Init(int source)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(!ft_init_done || font_file != ttx_font_file) {
|
||||
if(!ft_init_done || font_file != ttx_font_file || fontheight != oldfontheight) {
|
||||
printf("TuxTxt: init fontlibrary\n");
|
||||
if(ft_init_done) {
|
||||
FTC_Manager_Done(manager);
|
||||
@@ -2125,6 +2167,7 @@ int Init(int source)
|
||||
}
|
||||
font_file = ttx_font_file;
|
||||
ft_init_done = true;
|
||||
oldfontheight = fontheight;
|
||||
|
||||
ascender = (usettf ? fontheight * face->ascender / face->units_per_EM : 16);
|
||||
}
|
||||
@@ -2197,7 +2240,6 @@ int Init(int source)
|
||||
#else
|
||||
tuxtxt_start(tuxtxt_cache.vtxtpid, source);
|
||||
#endif
|
||||
fcntl(rc, F_SETFL, O_NONBLOCK);
|
||||
gethotlist();
|
||||
|
||||
if(use_gui)
|
||||
@@ -2791,7 +2833,7 @@ void Menu_Init(char *menu, int current_pid, int menuitem, int hotindex)
|
||||
|
||||
void ConfigMenu(int Init)
|
||||
{
|
||||
int val, menuitem = M_Start;
|
||||
int menuitem = M_Start;
|
||||
int current_pid = 0;
|
||||
int hotindex;
|
||||
int oldscreenmode, oldtrans = 0;
|
||||
@@ -2845,23 +2887,18 @@ void ConfigMenu(int Init)
|
||||
clearbbcolor = black;
|
||||
Menu_Init(menu, current_pid, menuitem, hotindex);
|
||||
|
||||
/* set blocking mode */
|
||||
val = fcntl(rc, F_GETFL);
|
||||
fcntl(rc, F_SETFL, val &~ O_NONBLOCK);
|
||||
|
||||
/* loop */
|
||||
do {
|
||||
if (GetRCCode() == 1)
|
||||
{
|
||||
int rc_num = -1;
|
||||
|
||||
if (
|
||||
#if (RC_1 > 0)
|
||||
RCCode >= RC_1 && /* generates a warning... */
|
||||
#endif
|
||||
RCCode <= RC_1+M_MaxDirect) /* direct access */
|
||||
if (CRCInput::isNumeric(RCCode))
|
||||
rc_num = CRCInput::getNumericValue(RCCode) -1; /* valid: 1 to M_MaxDirect */
|
||||
if (rc_num >= 0 && rc_num <= M_MaxDirect) /* direct access */
|
||||
{
|
||||
Menu_HighlightLine(menu, MenuLine[menuitem], 0);
|
||||
menuitem = RCCode-RC_1;
|
||||
menuitem = rc_num;
|
||||
Menu_HighlightLine(menu, MenuLine[menuitem], 1);
|
||||
|
||||
if (menuitem != M_PID) /* just select */
|
||||
@@ -3322,7 +3359,6 @@ void ConfigMenu(int Init)
|
||||
current_service = current_pid;
|
||||
// RenderMessage(ShowServiceName);
|
||||
|
||||
fcntl(rc, F_SETFL, O_NONBLOCK);
|
||||
RCCode = -1;
|
||||
if (oldscreenmode)
|
||||
SwitchScreenMode(oldscreenmode); /* restore divided screen */
|
||||
@@ -3383,8 +3419,6 @@ void ConfigMenu(int Init)
|
||||
|
||||
ClearBB(transp);
|
||||
CopyBB2FB();
|
||||
/* reset to nonblocking mode */
|
||||
fcntl(rc, F_SETFL, O_NONBLOCK);
|
||||
tuxtxt_cache.pageupdate = 1;
|
||||
RCCode = -1;
|
||||
if (oldscreenmode)
|
||||
@@ -3599,7 +3633,7 @@ void ColorKey(int target)
|
||||
|
||||
void PageCatching()
|
||||
{
|
||||
int val, byte;
|
||||
int byte;
|
||||
int oldzoommode = zoommode;
|
||||
|
||||
pagecatching = 1;
|
||||
@@ -3629,10 +3663,6 @@ void PageCatching()
|
||||
return;
|
||||
}
|
||||
|
||||
/* set blocking mode */
|
||||
val = fcntl(rc, F_GETFL);
|
||||
fcntl(rc, F_SETFL, val &~ O_NONBLOCK);
|
||||
|
||||
/* loop */
|
||||
do {
|
||||
GetRCCode();
|
||||
@@ -3671,7 +3701,6 @@ void PageCatching()
|
||||
case RC_HOME:
|
||||
case RC_HELP:
|
||||
case RC_MUTE:
|
||||
fcntl(rc, F_SETFL, O_NONBLOCK);
|
||||
tuxtxt_cache.pageupdate = 1;
|
||||
pagecatching = 0;
|
||||
RCCode = -1;
|
||||
@@ -3695,9 +3724,6 @@ void PageCatching()
|
||||
tuxtxt_cache.subpage = subp;
|
||||
else
|
||||
tuxtxt_cache.subpage = 0;
|
||||
|
||||
/* reset to nonblocking mode */
|
||||
fcntl(rc, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -3929,9 +3955,9 @@ void SwitchScreenMode(int newscreenmode)
|
||||
|
||||
if (screenmode==1) /* split with topmenu */
|
||||
{
|
||||
int x = CFrameBuffer::getInstance()->getScreenX();
|
||||
int w = CFrameBuffer::getInstance()->getScreenWidth();
|
||||
int h = CFrameBuffer::getInstance()->getScreenHeight();
|
||||
int x = screen_x;
|
||||
int w = screen_w;
|
||||
int h = screen_h;
|
||||
fw = fontwidth_topmenumain;
|
||||
|
||||
tx = 0; /* split means we start at the left edge */
|
||||
@@ -3958,18 +3984,20 @@ void SwitchScreenMode(int newscreenmode)
|
||||
}
|
||||
else /* 2: split with full height tv picture */
|
||||
{
|
||||
StartX = CFrameBuffer::getInstance()->getScreenX();
|
||||
StartX = screen_x;
|
||||
fw = fontwidth_small;
|
||||
tx = TV169FULLSTARTX;
|
||||
ty = TV169FULLSTARTY;
|
||||
tw = TV169FULLWIDTH;
|
||||
th = TV169FULLHEIGHT;
|
||||
displaywidth = CFrameBuffer::getInstance()->getScreenWidth()/2;
|
||||
displaywidth = screen_w / 2;
|
||||
}
|
||||
|
||||
setfontwidth(fw);
|
||||
|
||||
videoDecoder->Pig(tx, ty, tw, th, CFrameBuffer::getInstance()->getScreenWidth(true), CFrameBuffer::getInstance()->getScreenHeight(true));
|
||||
CFrameBuffer *f = CFrameBuffer::getInstance();
|
||||
videoDecoder->Pig(tx, ty, tw, th,
|
||||
f->getScreenWidth(true), f->getScreenHeight(true));
|
||||
#if 0
|
||||
int sm = 0;
|
||||
ioctl(pig, VIDIOC_OVERLAY, &sm);
|
||||
@@ -3991,8 +4019,8 @@ void SwitchScreenMode(int newscreenmode)
|
||||
#endif
|
||||
videoDecoder->Pig(-1, -1, -1, -1);
|
||||
|
||||
int x = CFrameBuffer::getInstance()->getScreenX();
|
||||
int w = CFrameBuffer::getInstance()->getScreenWidth();
|
||||
int x = screen_x;
|
||||
int w = screen_w;
|
||||
//int h = CFrameBuffer::getInstance()->getScreenHeight();
|
||||
int tx = 0;
|
||||
/* see comment above on the TTX window dimensions */
|
||||
@@ -4079,7 +4107,7 @@ void SwitchHintMode()
|
||||
|
||||
void RenderDRCS( //FIX ME
|
||||
unsigned char *s, /* pointer to char data, parity undecoded */
|
||||
unsigned char *d, /* pointer to frame buffer of top left pixel */
|
||||
fb_pixel_t *d, /* pointer to frame buffer of top left pixel */
|
||||
unsigned char *ax, /* array[0..12] of x-offsets, array[0..10] of y-offsets for each pixel */
|
||||
unsigned char fgcolor, unsigned char bgcolor)
|
||||
{
|
||||
@@ -4111,48 +4139,45 @@ void RenderDRCS( //FIX ME
|
||||
{
|
||||
// memset(d + ax[x], f1, ax[x+1] - ax[x]);
|
||||
for (ltmp=0 ; ltmp <= (ax[x+1]-ax[x]); ltmp++)
|
||||
{
|
||||
memmove(d + ax[x]*4 +ltmp*4,bgra[f1],4);
|
||||
}
|
||||
*(d + ax[x] + ltmp) = bgra[f1];
|
||||
}
|
||||
if (ax[x+7] > ax[x+6])
|
||||
{
|
||||
// memset(d + ax[x+6], f2, ax[x+7] - ax[x+6]); /* 2nd byte 6 pixels to the right */
|
||||
for (ltmp=0 ; ltmp <= (ax[x+7]-ax[x+6]); ltmp++)
|
||||
{
|
||||
memmove(d + ax[x+6]*4 +ltmp*4,bgra[f2],4);
|
||||
}
|
||||
|
||||
*(d + ax[x+6] + ltmp) = bgra[f2];
|
||||
}
|
||||
d += fix_screeninfo.line_length;
|
||||
d += stride;
|
||||
}
|
||||
d -= h * fix_screeninfo.line_length;
|
||||
d -= h * stride;
|
||||
}
|
||||
d += h * fix_screeninfo.line_length;
|
||||
d += h * stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DrawVLine(int x, int y, int l, int color)
|
||||
{
|
||||
unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length;
|
||||
fb_pixel_t *p = getFBp(&y);
|
||||
MARK_FB(x, y, 0, l);
|
||||
p += x + y * stride;
|
||||
|
||||
for ( ; l > 0 ; l--)
|
||||
{
|
||||
memmove(p,bgra[color],4);
|
||||
p += fix_screeninfo.line_length;
|
||||
*p = bgra[color];
|
||||
p += stride;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawHLine(int x, int y, int l, int color)
|
||||
{
|
||||
int ltmp;
|
||||
fb_pixel_t *p = getFBp(&y);
|
||||
MARK_FB(x, y, l, 0);
|
||||
if (l > 0)
|
||||
{
|
||||
for (ltmp=0; ltmp <= l; ltmp++)
|
||||
{
|
||||
memmove(lfb + x*4 + ltmp*4 + y * fix_screeninfo.line_length, bgra[color], 4);
|
||||
}
|
||||
*(p + x + ltmp + y * stride) = bgra[color];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4167,7 +4192,10 @@ void FillRectMosaicSeparated(int x, int y, int w, int h, int fgcolor, int bgcolo
|
||||
|
||||
void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color)
|
||||
{
|
||||
unsigned char *p = lfb + x0*4 + y0 * fix_screeninfo.line_length;
|
||||
fb_pixel_t *p = getFBp(&y0);
|
||||
MARK_FB(x0, y0, l0, h);
|
||||
p += x0 + y0 * stride;
|
||||
|
||||
int xoffset, l;
|
||||
int yoffset;
|
||||
int ltmp;
|
||||
@@ -4179,17 +4207,18 @@ void FillTrapez(int x0, int y0, int l0, int xoffset1, int h, int l1, int color)
|
||||
if (l > 0)
|
||||
{
|
||||
for (ltmp=0; ltmp <= l; ltmp++)
|
||||
{
|
||||
memmove(p + xoffset*4 +ltmp*4, bgra[color], 4);
|
||||
}
|
||||
*(p + xoffset + ltmp) = bgra[color];
|
||||
}
|
||||
p += fix_screeninfo.line_length;
|
||||
p += stride;
|
||||
}
|
||||
}
|
||||
void FlipHorz(int x, int y, int w, int h)
|
||||
{
|
||||
unsigned char *buf= new unsigned char[w*4];
|
||||
unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length;
|
||||
fb_pixel_t *p = getFBp(&y);
|
||||
MARK_FB(x, y, w, h);
|
||||
p += x + y * stride;
|
||||
|
||||
int w1,h1;
|
||||
if(buf != NULL){
|
||||
for (h1 = 0 ; h1 < h ; h1++)
|
||||
@@ -4197,9 +4226,9 @@ void FlipHorz(int x, int y, int w, int h)
|
||||
memmove(buf,p,w*4);
|
||||
for (w1 = 0 ; w1 < w ; w1++)
|
||||
{
|
||||
memmove(p+w1*4,buf+((w-w1)*4)-4,4);
|
||||
memmove(p + w1,buf+((w-w1)*4)-4,4);
|
||||
}
|
||||
p += fix_screeninfo.line_length;
|
||||
p += stride;
|
||||
}
|
||||
delete [] buf;
|
||||
}
|
||||
@@ -4207,13 +4236,17 @@ void FlipHorz(int x, int y, int w, int h)
|
||||
void FlipVert(int x, int y, int w, int h)
|
||||
{
|
||||
unsigned char *buf= new unsigned char[w*4];
|
||||
unsigned char *p = lfb + x*4 + y * fix_screeninfo.line_length, *p1, *p2;
|
||||
fb_pixel_t *p1, *p2;
|
||||
fb_pixel_t *p = getFBp(&y);
|
||||
MARK_FB(x, y, w, h);
|
||||
p += x + y * stride;
|
||||
|
||||
int h1;
|
||||
if(buf != NULL){
|
||||
for (h1 = 0 ; h1 < h/2 ; h1++)
|
||||
{
|
||||
p1 = (p+(h1*fix_screeninfo.line_length));
|
||||
p2 = (p+(h-(h1+1))*fix_screeninfo.line_length);
|
||||
p1 = (p + (h1 * stride));
|
||||
p2 = (p + (h - (h1 + 1)) * stride);
|
||||
memmove(buf,p1,w*4);
|
||||
memmove(p1,p2,w*4);
|
||||
memmove(p2,buf,w*4);
|
||||
@@ -4468,7 +4501,11 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
|
||||
else if (*aShapes[Char - 0x20] == S_ADT)
|
||||
{
|
||||
int x,y,f,c;
|
||||
unsigned char* p = lfb + PosX*4 + (PosY+yoffset)* fix_screeninfo.line_length;
|
||||
y = yoffset;
|
||||
fb_pixel_t *p = getFBp(&y);
|
||||
MARK_FB(PosX, PosY, curfontwidth, fontheight);
|
||||
p += PosX + PosY * stride;
|
||||
|
||||
for (y=0; y<fontheight;y++)
|
||||
{
|
||||
for (f=0; f<factor; f++)
|
||||
@@ -4476,9 +4513,9 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
|
||||
for (x=0; x<curfontwidth*xfactor;x++)
|
||||
{
|
||||
c = (y&4 ? (x/3)&1 :((x+3)/3)&1);
|
||||
memmove((p+x*4),bgra[(c ? fgcolor : bgcolor)],4);
|
||||
*(p + x) = bgra[(c ? fgcolor : bgcolor)];
|
||||
}
|
||||
p += fix_screeninfo.line_length;
|
||||
p += stride;
|
||||
}
|
||||
}
|
||||
PosX += curfontwidth;
|
||||
@@ -4512,8 +4549,10 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
|
||||
return;
|
||||
}
|
||||
axdrcs[12] = curfontwidth; /* adjust last x-offset according to position, FIXME: double width */
|
||||
int y = yoffset;
|
||||
fb_pixel_t *q = getFBp(&y);
|
||||
RenderDRCS(p,
|
||||
lfb + PosX*4 + (yoffset + PosY) * fix_screeninfo.line_length,
|
||||
q + PosX + PosY * stride,
|
||||
axdrcs, fgcolor, bgcolor);
|
||||
}
|
||||
else
|
||||
@@ -4779,7 +4818,7 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *p;
|
||||
fb_pixel_t *p;
|
||||
int f; /* running counter for zoom factor */
|
||||
|
||||
Row = factor * (ascender - sbit->top + TTFShiftY);
|
||||
@@ -4788,18 +4827,20 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
|
||||
if (ascender - sbit->top + TTFShiftY + sbit->height > fontheight)
|
||||
sbit->height = fontheight - ascender + sbit->top - TTFShiftY; /* limit char height to defined/calculated fontheight */
|
||||
|
||||
int y = yoffset;
|
||||
p = getFBp(&y);
|
||||
p += PosX + (PosY + Row) * stride; /* running pointer into framebuffer */
|
||||
|
||||
p = lfb + PosX*4 + (yoffset + PosY + Row) * fix_screeninfo.line_length; /* running pointer into framebuffer */
|
||||
for (Row = sbit->height; Row; Row--) /* row counts up, but down may be a little faster :) */
|
||||
{
|
||||
int pixtodo = (usettf ? sbit->width : curfontwidth);
|
||||
char *pstart = (char*) p;
|
||||
fb_pixel_t *pstart = p;
|
||||
|
||||
for (Bit = xfactor * (sbit->left + TTFShiftX); Bit > 0; Bit--) /* fill left margin */
|
||||
{
|
||||
for (f = factor-1; f >= 0; f--)
|
||||
memmove((p + f*fix_screeninfo.line_length),bgra[bgcolor],4);/*bgcolor*/
|
||||
p+=4;
|
||||
*(p + f * stride) = bgra[bgcolor];
|
||||
p++;
|
||||
if (!usettf)
|
||||
pixtodo--;
|
||||
}
|
||||
@@ -4819,14 +4860,14 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
|
||||
color = bgcolor;
|
||||
|
||||
for (f = factor-1; f >= 0; f--)
|
||||
memmove((p + f*fix_screeninfo.line_length),bgra[color],4);
|
||||
p+=4;
|
||||
*(p + f * stride) = bgra[color];
|
||||
p++;
|
||||
|
||||
if (xfactor > 1) /* double width */
|
||||
{
|
||||
for (f = factor-1; f >= 0; f--)
|
||||
memmove((p + f*fix_screeninfo.line_length),bgra[color],4);
|
||||
p+=4;
|
||||
*(p + f * stride) = bgra[color];
|
||||
p++;
|
||||
|
||||
if (!usettf)
|
||||
pixtodo--;
|
||||
@@ -4838,11 +4879,11 @@ void RenderChar(int Char, tstPageAttr *Attribute, int zoom, int yoffset)
|
||||
Bit > 0; Bit--) /* fill rest of char width */
|
||||
{
|
||||
for (f = factor-1; f >= 0; f--)
|
||||
memmove((p + f*fix_screeninfo.line_length),bgra[bgcolor],4);
|
||||
p+=4;
|
||||
*(p + f * stride) = bgra[bgcolor];
|
||||
p++;
|
||||
}
|
||||
|
||||
p = (unsigned char*) pstart + factor*fix_screeninfo.line_length;
|
||||
p = pstart + factor * stride;
|
||||
}
|
||||
|
||||
Row = ascender - sbit->top + sbit->height + TTFShiftY;
|
||||
@@ -5121,8 +5162,8 @@ void DoFlashing(int startrow)
|
||||
}
|
||||
PosY += fontheight*factor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RenderPage()
|
||||
{
|
||||
int row, col, byte, startrow = 0;;
|
||||
@@ -5193,7 +5234,7 @@ void RenderPage()
|
||||
fontwidth_topmenumain = (TV43STARTX-sx) / (40-nofirst);
|
||||
fontwidth_topmenusmall = (TVENDX - TOPMENUSTARTX) / TOPMENUCHARS;
|
||||
//fontwidth_small = (TV169FULLSTARTX-sx) / (40-nofirst);
|
||||
fontwidth_small = (CFrameBuffer::getInstance()->getScreenWidth()/2) / (40-nofirst);
|
||||
fontwidth_small = (screen_w / 2) / (40 - nofirst);
|
||||
switch(screenmode)
|
||||
{
|
||||
case 0:
|
||||
@@ -5201,7 +5242,7 @@ void RenderPage()
|
||||
displaywidth = ex - sx;
|
||||
break;
|
||||
case 2: setfontwidth(fontwidth_small);
|
||||
displaywidth = CFrameBuffer::getInstance()->getScreenWidth() / 2;
|
||||
displaywidth = screen_w / 2;
|
||||
break;
|
||||
}
|
||||
if (transpmode || (boxed && !screenmode))
|
||||
@@ -5444,7 +5485,7 @@ void CreateLine25()
|
||||
showlink(3, next_100);
|
||||
}
|
||||
|
||||
if (//tuxtxt_cache.bttok &&
|
||||
if (tuxtxt_cache.bttok &&
|
||||
screenmode == 1) /* TOP-Info present, divided screen -> create TOP overview */
|
||||
{
|
||||
char line[TOPMENUCHARS];
|
||||
@@ -5552,8 +5593,11 @@ void CreateLine25()
|
||||
|
||||
void CopyBB2FB()
|
||||
{
|
||||
unsigned char *src, *dst, *topsrc;
|
||||
fb_pixel_t *src, *dst, *topsrc;
|
||||
int fillcolor, i, screenwidth, swtmp;
|
||||
#ifdef HAVE_SPARK_HARDWARE
|
||||
CFrameBuffer *f = CFrameBuffer::getInstance();
|
||||
#endif
|
||||
|
||||
/* line 25 */
|
||||
if (!pagecatching && use_gui)
|
||||
@@ -5574,12 +5618,26 @@ void CopyBB2FB()
|
||||
if (ioctl(fb, FBIOPAN_DISPLAY, &var_screeninfo) == -1)
|
||||
perror("TuxTxt <FBIOPAN_DISPLAY>");
|
||||
#else
|
||||
memmove(lfb, lfb+fix_screeninfo.line_length * var_screeninfo.yres, fix_screeninfo.line_length*var_screeninfo.yres);
|
||||
#ifdef HAVE_SPARK_HARDWARE
|
||||
f->blit2FB(lbb, var_screeninfo.xres, var_screeninfo.yres, 0, 0, 0, 0, true);
|
||||
#else
|
||||
if ((uint32_t)stride > var_screeninfo.xres) {
|
||||
fb_pixel_t *lfb_ = lfb;
|
||||
fb_pixel_t *lbb_ = lbb;
|
||||
for (uint32_t i1 = 0; i1 < var_screeninfo.yres; i1++) {
|
||||
memcpy(lfb_, lbb_, var_screeninfo.xres * sizeof(fb_pixel_t));
|
||||
lfb_ += stride;
|
||||
lbb_ += stride;
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(lfb, lbb, fix_screeninfo.line_length*var_screeninfo.yres);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* adapt background of backbuffer if changed */
|
||||
if (StartX > 0 && *lfb != *(lfb + fix_screeninfo.line_length * var_screeninfo.yres)) {
|
||||
FillBorder(*(lfb + fix_screeninfo.line_length * var_screeninfo.yoffset));
|
||||
if (StartX > 0 && *lfb != *lbb) {
|
||||
FillBorder(*lbb);
|
||||
// ClearBB(*(lfb + var_screeninfo.xres * var_screeninfo.yoffset));
|
||||
}
|
||||
|
||||
@@ -5591,8 +5649,11 @@ void CopyBB2FB()
|
||||
return;
|
||||
}
|
||||
|
||||
src = dst = topsrc = lfb + StartY*fix_screeninfo.line_length;
|
||||
src = topsrc = lbb + StartY * stride;
|
||||
dst = lfb + StartY * stride;
|
||||
|
||||
#ifdef USE_FBPAN
|
||||
#error USE_FBPAN code is not working right now.
|
||||
if (var_screeninfo.yoffset)
|
||||
dst += fix_screeninfo.line_length * var_screeninfo.yres;
|
||||
else
|
||||
@@ -5600,9 +5661,10 @@ void CopyBB2FB()
|
||||
src += fix_screeninfo.line_length * var_screeninfo.yres;
|
||||
topsrc += fix_screeninfo.line_length * var_screeninfo.yres;
|
||||
}
|
||||
#endif
|
||||
/* copy line25 in normal height */
|
||||
if (!pagecatching )
|
||||
memmove(dst+(24*fontheight)*fix_screeninfo.line_length, src + (24*fontheight)*fix_screeninfo.line_length, fix_screeninfo.line_length*fontheight);
|
||||
memmove(dst + (24 * fontheight) * stride, src + (24 * fontheight) * stride, stride * fontheight);
|
||||
|
||||
if (transpmode)
|
||||
fillcolor = transp;
|
||||
@@ -5610,54 +5672,60 @@ void CopyBB2FB()
|
||||
fillcolor = FullScrColor;
|
||||
|
||||
if (zoommode == 2)
|
||||
src += 12*fontheight*fix_screeninfo.line_length;
|
||||
src += 12 * fontheight * stride;
|
||||
|
||||
/* copy topmenu in normal height (since PIG also keeps dimensions) */
|
||||
if (screenmode == 1)
|
||||
{
|
||||
unsigned char *topdst = dst;
|
||||
|
||||
screenwidth = ( TV43STARTX ) * 4;
|
||||
size_t width = ex * sizeof(fb_pixel_t) - screenwidth;
|
||||
screenwidth = ( TV43STARTX );
|
||||
#ifdef HAVE_SPARK_HARDWARE
|
||||
int cx = var_screeninfo.xres - TV43STARTX; /* x start */
|
||||
int cw = TV43STARTX; /* width */
|
||||
int cy = StartY;
|
||||
int ch = 24*fontheight;
|
||||
f->blit2FB(lbb, cw, ch, cx, cy, cx, cy, true);
|
||||
#else
|
||||
fb_pixel_t *topdst = dst;
|
||||
size_t width = (ex - screenwidth) * sizeof(fb_pixel_t);
|
||||
|
||||
topsrc += screenwidth;
|
||||
topdst += screenwidth;
|
||||
for (i=0; i < 24*fontheight; i++)
|
||||
{
|
||||
memmove(topdst, topsrc, width);
|
||||
topdst += fix_screeninfo.line_length;
|
||||
topsrc += fix_screeninfo.line_length;
|
||||
topdst += stride;
|
||||
topsrc += stride;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (screenmode == 2)
|
||||
screenwidth = ( TV169FULLSTARTX ) * 4;
|
||||
screenwidth = ( TV169FULLSTARTX );
|
||||
else
|
||||
screenwidth = fix_screeninfo.line_length;//var_screeninfo.xres;
|
||||
screenwidth = stride;
|
||||
|
||||
for (i = StartY; i>0;i--)
|
||||
{
|
||||
for (swtmp=0; swtmp<=screenwidth; swtmp++)
|
||||
{
|
||||
memmove(dst - i*fix_screeninfo.line_length+swtmp*4, bgra[fillcolor], 4);
|
||||
}
|
||||
*(dst - i * stride + swtmp) = bgra[fillcolor];
|
||||
}
|
||||
|
||||
for (i = 12*fontheight; i; i--)
|
||||
{
|
||||
memmove(dst, src, screenwidth);
|
||||
dst += fix_screeninfo.line_length;
|
||||
memmove(dst, src, screenwidth);
|
||||
dst += fix_screeninfo.line_length;
|
||||
src += fix_screeninfo.line_length;
|
||||
memmove(dst, src, screenwidth * sizeof(fb_pixel_t));
|
||||
dst += stride;
|
||||
memmove(dst, src, screenwidth * sizeof(fb_pixel_t));
|
||||
dst += stride;
|
||||
src += stride;
|
||||
}
|
||||
|
||||
for (i = var_screeninfo.yres - StartY - 25*fontheight; i >= 0;i--)
|
||||
{
|
||||
for (swtmp=0; swtmp<= screenwidth;swtmp++)
|
||||
{
|
||||
memmove(dst + fix_screeninfo.line_length*(fontheight+i)+swtmp*4, bgra[fillcolor], 4);
|
||||
}
|
||||
*(dst + stride * (fontheight + i) + swtmp) = bgra[fillcolor];
|
||||
}
|
||||
#ifdef HAVE_SPARK_HARDWARE
|
||||
f->mark(0, 0, var_screeninfo.xres, var_screeninfo.yres);
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -5975,8 +6043,8 @@ void DecodePage()
|
||||
RenderDRCS(
|
||||
page_char + 20 * (DRCSCOLS * row + col + 2),
|
||||
lfb
|
||||
+ (StartY + fontheight + DRCSYSPC * row + var_screeninfo.yres - var_screeninfo.yoffset) * fix_screeninfo.line_length
|
||||
+ (StartX + DRCSXSPC * col)*4,
|
||||
+ (StartY + fontheight + DRCSYSPC * row + var_screeninfo.yres - var_screeninfo.yoffset) * stride
|
||||
+ (StartX + DRCSXSPC * col),
|
||||
ax, white, black);
|
||||
|
||||
memset(page_char + 40, 0xff, 24*40); /* don't render any char below row 0 */
|
||||
@@ -6347,6 +6415,21 @@ void DecodePage()
|
||||
/******************************************************************************
|
||||
* GetRCCode *
|
||||
******************************************************************************/
|
||||
int GetRCCode()
|
||||
{
|
||||
neutrino_msg_t msg;
|
||||
neutrino_msg_data_t data;
|
||||
g_RCInput->getMsg_ms(&msg, &data, 40);
|
||||
RCCode = -1;
|
||||
|
||||
if (msg <= CRCInput::RC_MaxRC) {
|
||||
RCCode = msg;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
int GetRCCode()
|
||||
{
|
||||
@@ -6420,7 +6503,7 @@ printf("[tuxtxt] new key, code %X\n", RCCode);
|
||||
}
|
||||
|
||||
RCCode = -1;
|
||||
usleep(1000000/100);
|
||||
usleep(1000000/25);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -6485,6 +6568,7 @@ int GetRCCode()
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
/* Local Variables: */
|
||||
/* indent-tabs-mode:t */
|
||||
/* tab-width:3 */
|
||||
|
Reference in New Issue
Block a user