@@ -351,6 +351,9 @@ void OnGridGetDispInfo(NMLVDISPINFOW *pdi) {
351351 ColumnMeta * cm = & g_colMeta [col ];
352352 if (cm -> isAutoInc ) {
353353 pdi -> item .pszText = L"(auto)" ;
354+ } else if (!cm -> notNull && !cm -> hasDefault ) {
355+ /* Nullable without default - will be NULL if not filled */
356+ pdi -> item .pszText = L"(null)" ;
354357 } else {
355358 pdi -> item .pszText = L"" ;
356359 }
@@ -482,6 +485,7 @@ void PopulateGrid(void) {
482485
483486static int g_commitNull = 0 ; /* Flag to commit NULL instead of text value */
484487static int g_inCommit = 0 ; /* Guard against re-entry */
488+ static int g_cellDirty = 0 ; /* Track if user typed anything in cell */
485489
486490/* Find next editable column (skips autoincrement) */
487491static int NextEditableColumn (int col , int direction ) {
@@ -561,6 +565,15 @@ static LRESULT CALLBACK EditOverlayProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR
561565 if (HandleEditKey (msg , wParam )) return 0 ;
562566 }
563567
568+ /* Track dirty state - user typed something */
569+ if (msg == WM_CHAR && wParam >= 32 ) {
570+ g_cellDirty = 1 ;
571+ }
572+ /* Also mark dirty on backspace/delete (user is modifying) */
573+ if (msg == WM_KEYDOWN && (wParam == VK_BACK || wParam == VK_DELETE )) {
574+ g_cellDirty = 1 ;
575+ }
576+
564577 /* Commit on focus loss */
565578 if (msg == WM_KILLFOCUS && g_hwndEditOverlay ) {
566579 CommitCellEdit ();
@@ -580,6 +593,9 @@ static void StartCellEdit(int row, int col) {
580593 if (!g_editMode || !g_hwndGrid || row < 0 ) return ;
581594 if (g_hwndEditOverlay ) CancelCellEdit (); /* Close any existing edit */
582595
596+ /* Reset dirty flag for new edit */
597+ g_cellDirty = 0 ;
598+
583599 /* Placeholder row (new row) - enter insert mode */
584600 if (row == g_lastResultRows ) {
585601 /* Don't allow editing autoincrement columns */
@@ -953,8 +969,11 @@ static void CommitCellEdit(void) {
953969 if (setNull ) {
954970 /* Explicit NULL - use marker */
955971 StorePendingValue (g_editCol , "\x01" );
972+ } else if (!g_cellDirty && newVal [0 ] == '\0' ) {
973+ /* Cell untouched and empty - don't store anything (will be NULL) */
974+ /* StorePendingValue not called - leaves as NULL */
956975 } else {
957- /* Store value (including empty string) */
976+ /* Store value (including empty string if user typed then deleted ) */
958977 StorePendingValue (g_editCol , newVal );
959978 }
960979
0 commit comments