→ Metro123Star: 測試報告:PttChrome有*[3m的效果 06/26 19:29
→ Metro123Star: 測試報告:PiTT可顯示*[3m效果 06/26 19:33
> -------------------------------------------------------------------------- <
作者: holishing ( ) 看板: PttNewhand
標題: Re: [問題] 色碼 *[3m
時間: Thu Jun 27 00:10:30 2019
先講結論
只要你是用一般的終端機(包含BBS瀏覽器)
ESC[3m 顯示的就是「反白」
(注意那個你看到的 * 以終端機輸出而言它就是 ESC 跳脫字元)
八卦是原本這個控制碼本來是拿來都做「字體斜體」用的
但或許可能因為大多數終端機都還沒支援這類標準
於是 pttbbs 程式所用的 pfterm 在處理這部分時都直接轉換成反白
有興趣的人可以參考相關原始碼:
https://github.com/ptt/pttbbs/blob/master/mbbsd/pfterm.c#L1672
或是看它上面註解說明
如果是其他 BBS 的話,則要看它用的終端機字元處理的部分有沒有過濾到這類字元
以及你拿來連 BBS 的客戶端 (client, 瀏覽器之類的) 有沒有支援囉
※ 引述《Metro123Star (ful ru04q06)》之銘言:
: 我在發文上色都是按^C跳出*[m的ANSI控制碼
: 然後按照色碼代號上色
: 其中已知這裡面現在可以填寫的有
: 亮字1
: 閃爍5
: 前景(文字)色3x (示範35)
: 背景色4x (示範41)
: 然後可以自由組合 例如亮閃綠底黃字 *[1;5;33;42m
: 但是我發現一個很奇怪的指令
: 單獨使用*[3m會出現白底黑字
: 與*[30;47m一樣是這個效果
: 打*[3;34m會長得像這樣 與*[34;47m相同白底藍字
: 打*[3;46m會長得像這樣 與*[30;46m相同青底黑字
: (如果你的瀏覽方式看不出來請按反斜線\切換原始ANSI控制碼模式)
: 我是用Mac內建Terminal以 ssh [email protected] 上站可以看到*[3m的效果
: 可是用網頁版(文章網址)在瀏覽器開啟時*[3m的效果是不存在的
: 請問這是什麼原因造成?
--
你知道PTT有小天使嗎? 祂能幫助你唷! 小主人我來了^Q^ -
◥ ●β
、HELP 想呼叫屬於你的小天使嗎? /◥=
` 〈○〉 ▃▃▃ 只要按hh,就可以了唷!! Δ
新 ◥ >_<~
// ▅▅▅ 快按下"hh"呼叫你的小天使吧!\(≧▽ν≦)ωgarnier
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 220.136.129.3 (臺灣)
※ 文章網址: https://www.ptt.cc/bbs/PttNewhand/M.1561565435.A.C52.html
推 BigCat: 推 06/27 00:10
> -------------------------------------------------------------------------- <
[相關程式碼]
case 'm': // SGR: CSI n [;k] m
// Sets SGR (Select Graphic Rendition) parameters.
// After CSI can be zero or more parameters separated with ;.
// With no parameters, CSI m is treated as CSI 0 m (reset / normal),
// which is typical of most of the ANSI codes.
// ---------------------------------------------------------
// SGR implementation:
// SGR 0 (reset/normal) is supported.
// SGR 1 (intensity: bold) is supported.
// SGR 2 (intensity: faint) is not supported.
// SGR 3 (italic: on) is not supported. (converted to
inverse?)
// SGR 4 (underline: single) is not supported.
// SGR 5 (blink: slow) is supported.
// SGR 6 (blink: rapid) is converted to (blink: slow)
// SGR 7 (image: negative) is partially supported (not a really
attribute).
// SGR 8 (conceal) is not supported.
// SGR 21(underline: double) is not supported.
// SGR 22(intensity: normal) is supported.
// SGR 24(underline: none) is not supported.
// SGR 25(blink: off) is supported.
// SGR 27(image: positive) is not supported.
// SGR 28(reveal) is not supported.
// SGR 30-37 (FG) is supported.
// SGR 39 (FG-reset) is supported.
// SGR 40-47 (BG) is supported.
// SGR 49 (BG-reset) is supported.
if (n == -1) // first param
n = 0;
while (n > -1)
{
if (n >= 30 && n <= 37)
{
// set foreground
attrsetfg(n - 30);
}
else if (n >= 40 && n <= 47)
{
// set background
attrsetbg(n - 40);
}
else switch(n)
{
case 0:
attrset(FTATTR_DEFAULT);
break;
case 1:
attrset(attrget() | FTATTR_BOLD);
break;
case 22:
attrset(attrget() & ~FTATTR_BOLD);
break;
case 5:
case 6:
attrset(attrget() | FTATTR_BLINK);
break;
case 25:
attrset(attrget() & ~FTATTR_BLINK);
break;
case 3:
case 7:
{
ftattr a = attrget();
attrsetfg(FTATTR_GETBG(a));
attrsetbg(FTATTR_GETFG(a));
}
break;
case 39:
attrsetfg(FTATTR_DEFAULT_FG);
break;
case 49:
attrsetbg(FTATTR_DEFAULT_BG);
break;
}
// parse next command
n = -1;
if (*p == ';')
{
n = 0;
p++;
}
else if (isdigit(*p))
{
n = atoi(p);
while (isdigit(*p)) p++;
if (*p == ';')
p++;
}
}
break;
default: // unknown command.
break;
}
}
int
fterm_chattr(char *s, ftattr oattr, ftattr nattr)
{
ftattr
fg, bg, bold, blink,
ofg, obg, obold, oblink;
char lead = 1;
if (oattr == nattr)
return 0;
*s++ = ESC_CHR;
*s++ = '[';
// optimization: reset as default
if (nattr == FTATTR_DEFAULT)
{
*s++ = 'm';
*s++ = 0;
return 1;
}
fg = FTATTR_GETFG(nattr);
bg = FTATTR_GETBG(nattr);
bold = (nattr & FTATTR_BOLD) ? 1 : 0;
blink = (nattr & FTATTR_BLINK)? 1 : 0;
ofg = FTATTR_GETFG(oattr);
obg = FTATTR_GETBG(oattr);
obold = (oattr & FTATTR_BOLD) ? 1 : 0;
oblink = (oattr & FTATTR_BLINK)? 1 : 0;
// we dont use "disable blink/bold" commands,
// so if these settings are changed then we must reset.
// another case is changing background to default background -
// better use "RESET" to override it.
// Same for foreground.
// Possible optimization: when blink/bold on, don't RESET
// for background change?
if ((oblink != blink && !blink) ||
(obold != bold && !bold) ||
(bg == FTATTR_DEFAULT_BG && obg != bg) ||
(fg == FTATTR_DEFAULT_FG && ofg != fg) )
{
// lead must be 1 since this is the first check.
// We have dead code (else *s++) here but that's simply to ease moving
// code around.
if (lead) lead = 0; else *s++ = ';';
*s++ = '0';
ofg = FTATTR_DEFAULT_FG;
obg = FTATTR_DEFAULT_BG;
obold = 0; oblink = 0;
}
if (bold && !obold)
{
if (lead) lead = 0; else *s++ = ';';
*s++ = '1';
#ifdef FTCONF_WORKAROUND_BOLD
// Issue here:
// PacketSite does not understand ESC[1m. It needs ESC[1;37m
// NetTerm defaults bold color to yellow.
// As a result, we use ESC[1;37m for the case.
if (fg == FTATTR_DEFAULT_FG)
ofg = ~ofg;
#endif // FTCONF_WORKAROUND_BOLD
}
if (blink && !oblink)
{
if (lead) lead = 0; else *s++ = ';';
*s++ = '5'; // XXX 5(slow) or 6(fast)?
}
if (ofg != fg)
{
if (lead) lead = 0; else *s++ = ';';
*s++ = '3';
*s++ = '0' + fg;
}
if (obg != bg)
{
if (lead) lead = 0; else *s++ = ';';
*s++ = '4';
*s++ = '0' + bg;
}
*s++ = 'm';
*s++ = 0;
return 1;
}
int
fterm_strdlen(const char *s)
{
char ansi = 0;
int sz = 0;
// the logic should match outc().
while (s && *s)
{
if (!ansi) // ansi == 0
{
switch(*s)
{
case ESC_CHR:
ansi++;
break;
case '\r':
case '\n':
break;
case '\b':
if (sz) sz--;
break;
case '\t':
// XXX how to deal with this?
sz ++;
break;
default:
if (!iscntrl((unsigned char)*s))
sz++;
break;
}
}
else if (ansi == 1)
{
if (*s == '[')
ansi++;
else
ansi = 0;
}
else if (!ANSI_IS_PARAM(*s)) // ansi == 2
{
// TODO outc() take max to FTCMD_MAXLEN now...
ansi = 0;
}
s++;
}
return sz;
}