]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improve columnar layout in QRF so that it correctly deals with control
authordrh <>
Sat, 15 Nov 2025 00:23:09 +0000 (00:23 +0000)
committerdrh <>
Sat, 15 Nov 2025 00:23:09 +0000 (00:23 +0000)
characters, and especially tabs.

FossilOrigin-Name: 0650e2b83170b44c1ba944259a96d41e1a14a57004d4f1f80dc5640ae837a81e

ext/qrf/qrf.c
manifest
manifest.uuid
test/qrf01.test

index 8eb1f2d1cf90d6f552000862e1f4b8f4401bd2a1..e5181caba231f53d3dc3d6214059767a0d8df4df 100644 (file)
@@ -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( i<nVal ){
+    unsigned char c = z[i];
+    if( c<' ' ){
+      int k;
+      sqlite3_str_append(pOut, (const char*)z, i);
+      nVal -= i;
+      z += i;
+      i = 0;
+      if( c=='\033' && (k = qrfIsVt100(z))>0 ){
+        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, ' ');
   }
 }
index 68225d739801b541b6f77b5727ecc1c89586d325..f5d30d1a1ed1c76867a2d19af3b5c0226b0287a6 100644 (file)
--- 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.
index 6df7b61b653a3ec4d141c96623b7b1c56037ff52..aaff16ad7bf701fa8a01e5a4dbe6c3f620e62575 100644 (file)
@@ -1 +1 @@
-2e07bc29ab1ca66049337f2cfbefcd57bdcd691a381b309fb8a5db6e72e56d03
+0650e2b83170b44c1ba944259a96d41e1a14a57004d4f1f80dc5640ae837a81e
index 99e3795d0128defe868030590898ee7a1bc52916..a9f6d4c83dbeebbed0a80c9c34a90df80542a382 100644 (file)
@@ -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