From: drh <> Date: Sat, 15 Nov 2025 00:23:09 +0000 (+0000) Subject: Improve columnar layout in QRF so that it correctly deals with control X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7a0d5bdd29984a6ee4580ed37937b66274854e83;p=thirdparty%2Fsqlite.git Improve columnar layout in QRF so that it correctly deals with control characters, and especially tabs. FossilOrigin-Name: 0650e2b83170b44c1ba944259a96d41e1a14a57004d4f1f80dc5640ae837a81e --- diff --git a/ext/qrf/qrf.c b/ext/qrf/qrf.c index 8eb1f2d1cf..e5181caba2 100644 --- a/ext/qrf/qrf.c +++ b/ext/qrf/qrf.c @@ -1175,6 +1175,8 @@ static void qrfWrapLine( } if( c==0x1b && (k = qrfIsVt100(&z[i]))>0 ){ i += k-1; + }else{ + n++; } } if( c==0 ){ @@ -1320,6 +1322,60 @@ static void qrfLoadAlignment(qrfColData *pData, Qrf *p){ } } +/* +** Append nVal bytes of text from zVal onto the end of pOut. +** Convert tab characters in zVal to the appropriate number of +** spaces. +*/ +static void qrfAppendWithTabs( + sqlite3_str *pOut, /* Append text here */ + const char *zVal, /* Text to append */ + int nVal /* Use only the first nVal bytes of zVal[] */ +){ + int i = 0; + unsigned int col = 0; + unsigned char *z = (unsigned char *)zVal; + while( i0 ){ + sqlite3_str_append(pOut, (const char*)z, k); + z += k; + nVal -= k; + }else if( c=='\t' ){ + k = 8 - (col&7); + sqlite3_str_appendchar(pOut, k, ' '); + col += k; + z++; + nVal--; + }else{ + char zCtrlPik[4]; + col++; + zCtrlPik[0] = 0xe2; + zCtrlPik[1] = 0x90; + zCtrlPik[2] = 0x80+c; + sqlite3_str_append(pOut, zCtrlPik, 3); + z++; + nVal--; + } + }else if( (0x80&c)==0 ){ + i++; + col++; + }else{ + int u = 0; + int len = sqlite3_qrf_decode_utf8(&z[i], &u); + i += len; + col += sqlite3_qrf_wcwidth(u); + } + } + sqlite3_str_append(pOut, (const char*)z, i); +} + /* ** Output horizontally justified text into pOut. The text is the ** first nVal bytes of zVal. Include nWS bytes of whitespace, either @@ -1337,15 +1393,15 @@ static void qrfPrintAligned( if( eAlign==QRF_ALIGN_Center ){ /* Center the text */ sqlite3_str_appendchar(pOut, nWS/2, ' '); - sqlite3_str_append(pOut, zVal, nVal); + qrfAppendWithTabs(pOut, zVal, nVal); sqlite3_str_appendchar(pOut, nWS - nWS/2, ' '); }else if( eAlign==QRF_ALIGN_Right){ /* Right justify the text */ sqlite3_str_appendchar(pOut, nWS, ' '); - sqlite3_str_append(pOut, zVal, nVal); + qrfAppendWithTabs(pOut, zVal, nVal); }else{ /* Left justify the next */ - sqlite3_str_append(pOut, zVal, nVal); + qrfAppendWithTabs(pOut, zVal, nVal); sqlite3_str_appendchar(pOut, nWS, ' '); } } diff --git a/manifest b/manifest index 68225d7398..f5d30d1a1e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\suse\sof\sthe\snew\ssqlite3_str_free()\sinterface\sin\sthe\sCLI. -D 2025-11-14T21:49:27.250 +C Improve\scolumnar\slayout\sin\sQRF\sso\sthat\sit\scorrectly\sdeals\swith\scontrol\ncharacters,\sand\sespecially\stabs. +D 2025-11-15T00:23:09.446 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -417,7 +417,7 @@ F ext/misc/windirent.h 02211ce51f3034c675f2dbf4d228194d51b3ee05734678bad5106fff6 F ext/misc/zipfile.c 09e6e3a3ff40a99677de3c0bc6569bd5f4709b1844ac3d1c1452a456c5a62f1c F ext/misc/zorder.c bddff2e1b9661a90c95c2a9a9c7ecd8908afab5763256294dd12d609d4664eee F ext/qrf/README.md 09dd538966d8ee32598fc010e7fe6755bd7190494953a02960a9c81197d20cf3 -F ext/qrf/qrf.c 0351a18ee34603f70a0a166c7ee2c17dd0306ca7b3ace1f797885f5464df8c8c +F ext/qrf/qrf.c d84c787719d464d399d57e2f3c00b28a9a3ce7e2217f231a7948800818ad5975 F ext/qrf/qrf.h b4b3489b3b3683523fd248d15cf5945830643b036943efacdb772a3e00367aa2 F ext/rbu/rbu.c 801450b24eaf14440d8fd20385aacc751d5c9d6123398df41b1b5aa804bf4ce8 F ext/rbu/rbu1.test 25870dd7db7eb5597e2b4d6e29e7a7e095abf332660f67d89959552ce8f8f255 @@ -1507,7 +1507,7 @@ F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224c F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/pushdown.test 46a626ef1c0ca79b85296ff2e078b9da20a50e9b804b38f441590c3987580ddd -F test/qrf01.test de83f4be443e17b4e3b9338ab6a574e259702ccdb6526f9375a977e21cfec307 +F test/qrf01.test f46f498e447d988b52dfa1cd45c683b7212bb2056741a4eff306df185b9c00b1 F test/qrf02.test 39b4afdc000bedccdafc0aecf17638df67a67aaa2d2942865ae6abcc48ba0e92 F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 @@ -2175,8 +2175,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P c25f8fdedd8d68e3551a445e24e1c60e105e18f9cf8f1badcbb77a58974f3381 -R 6709cc240d8387680d8df0a08649ae6f +P 2e07bc29ab1ca66049337f2cfbefcd57bdcd691a381b309fb8a5db6e72e56d03 +R 92baa41b393aca983481dff9605375cf U drh -Z 635ab109ed8a23b9e3c629d94c6b696e +Z 760acd97643ffb8533b6e177d763be56 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 6df7b61b65..aaff16ad7b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2e07bc29ab1ca66049337f2cfbefcd57bdcd691a381b309fb8a5db6e72e56d03 +0650e2b83170b44c1ba944259a96d41e1a14a57004d4f1f80dc5640ae837a81e diff --git a/test/qrf01.test b/test/qrf01.test index 99e3795d01..a9f6d4c83d 100644 --- a/test/qrf01.test +++ b/test/qrf01.test @@ -777,4 +777,89 @@ do_test 7.4 { abcdefghijklmnop|abcぁdefかghiのj... } +do_test 8.0 { + set result "\n[db format -style table { + WITH c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<10) + SELECT 'aaa' AS 'a', format('%.*c',n,'b')||char(9)||'xx' AS x FROM c}]" +} { ++-----+--------------------+ +| a | x | ++-----+--------------------+ +| aaa | b xx | +| aaa | bb xx | +| aaa | bbb xx | +| aaa | bbbb xx | +| aaa | bbbbb xx | +| aaa | bbbbbb xx | +| aaa | bbbbbbb xx | +| aaa | bbbbbbbb xx | +| aaa | bbbbbbbbb xx | +| aaa | bbbbbbbbbb xx | ++-----+--------------------+ +} +do_test 8.1 { + set result "\n[db format -style table { + WITH c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<10) + SELECT 'aaaa' AS 'a', format('%.*c',n,'b')||char(9)||'xx' AS x FROM c}]" +} { ++------+--------------------+ +| a | x | ++------+--------------------+ +| aaaa | b xx | +| aaaa | bb xx | +| aaaa | bbb xx | +| aaaa | bbbb xx | +| aaaa | bbbbb xx | +| aaaa | bbbbbb xx | +| aaaa | bbbbbbb xx | +| aaaa | bbbbbbbb xx | +| aaaa | bbbbbbbbb xx | +| aaaa | bbbbbbbbbb xx | ++------+--------------------+ +} +do_test 8.3 { + set result "\n[db format -style table -esc off { + WITH c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<15) + SELECT 'aaa' AS 'a',n, 'xx'||char(n)||'yy' AS xy FROM c + WHERE n NOT IN (8,10,13,14)}]" +} { ++-----+----+------------+ +| a | n | xy | ++-----+----+------------+ +| aaa | 1 | xx␁yy | +| aaa | 2 | xx␂yy | +| aaa | 3 | xx␃yy | +| aaa | 4 | xx␄yy | +| aaa | 5 | xx␅yy | +| aaa | 6 | xx␆yy | +| aaa | 7 | xx␇yy | +| aaa | 9 | xx yy | +| aaa | 11 | xx␋yy | +| aaa | 12 | xx␌yy | +| aaa | 15 | xx␏yy | ++-----+----+------------+ +} +do_test 8.4 { + set result "\n[db format -style table -esc off { + WITH c(n) AS (VALUES(1) UNION ALL SELECT n+1 FROM c WHERE n<15) + SELECT 'aaa' AS 'a',n, 'xx'||char(n)||'yy'||char(9)||'zz' AS xyz FROM c + WHERE n NOT IN (8,10,13,14)}]" +} { ++-----+----+--------------------+ +| a | n | xyz | ++-----+----+--------------------+ +| aaa | 1 | xx␁yy zz | +| aaa | 2 | xx␂yy zz | +| aaa | 3 | xx␃yy zz | +| aaa | 4 | xx␄yy zz | +| aaa | 5 | xx␅yy zz | +| aaa | 6 | xx␆yy zz | +| aaa | 7 | xx␇yy zz | +| aaa | 9 | xx yy zz | +| aaa | 11 | xx␋yy zz | +| aaa | 12 | xx␌yy zz | +| aaa | 15 | xx␏yy zz | ++-----+----+--------------------+ +} + finish_test