@@ -33,7 +33,7 @@ void CreateGridView(HWND hwndParent, int x, int y, int cx, int cy) {
3333 HIMAGELIST hIml ;
3434
3535 g_hwndGrid = CreateWindowExW (0 , WC_LISTVIEWW , NULL ,
36- WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_OWNERDATA ,
36+ WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_OWNERDATA ,
3737 x , y , cx , cy , hwndParent , (HMENU )IDC_GRID , g_hInst , NULL );
3838
3939 /* Enable full row select and grid lines */
@@ -181,12 +181,9 @@ LRESULT CALLBACK GridProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
181181 }
182182 return 0 ;
183183 }
184- /* Delete - Delete selected row (only in edit mode, not placeholder ) */
184+ /* Delete - Delete selected rows (only in edit mode) */
185185 if (wParam == VK_DELETE && g_editMode ) {
186- int sel = ListView_GetNextItem (g_hwndGrid , -1 , LVNI_SELECTED );
187- if (sel >= 0 && sel < g_lastResultRows ) {
188- DeleteSelectedRow ();
189- }
186+ DeleteSelectedRow ();
190187 return 0 ;
191188 }
192189 /* Escape - Cancel insert mode if active (when not in cell edit) */
@@ -794,17 +791,24 @@ static void CancelCellEdit(void) {
794791}
795792
796793static void DeleteSelectedRow (void ) {
797- int sel , dataRow , rowidIdx ;
794+ int sel , count , dataRow , rowidIdx , deleted , i ;
798795 char * rowid ;
799796 char sql [256 ];
800797 char tableName [128 ];
801798 char * p ;
802799 const char * s ;
803800 char * errmsg = NULL ;
804801 int rc ;
805-
806- sel = ListView_GetNextItem (g_hwndGrid , -1 , LVNI_SELECTED );
807- if (sel < 0 ) return ;
802+ wchar_t msg [64 ];
803+ char * * rowids ;
804+
805+ /* Count selected rows (excluding placeholder) */
806+ count = 0 ;
807+ sel = -1 ;
808+ while ((sel = ListView_GetNextItem (g_hwndGrid , sel , LVNI_SELECTED )) >= 0 ) {
809+ if (sel < g_lastResultRows ) count ++ ;
810+ }
811+ if (count < 1 ) return ;
808812
809813 /* Save table name before it gets cleared */
810814 s = g_editTableName ;
@@ -813,43 +817,78 @@ static void DeleteSelectedRow(void) {
813817 * p = '\0' ;
814818
815819 /* Confirm deletion */
816- if (MessageBoxW (g_hwndMain , L"Delete this row?" , L"Confirm Delete" ,
820+ if (count == 1 )
821+ lstrcpyW (msg , L"Delete this row?" );
822+ else
823+ wsprintfW (msg , L"Delete %d rows?" , count );
824+ if (MessageBoxW (g_hwndMain , msg , L"Confirm Delete" ,
817825 MB_YESNO | MB_ICONQUESTION ) != IDYES )
818826 return ;
819827
820- /* Get rowid */
821- dataRow = g_sortIndex ? g_sortIndex [sel ] : sel ;
822- rowidIdx = (dataRow + 1 ) * g_lastResultCols ;
823- rowid = g_lastResult [rowidIdx ];
824-
825- if (!rowid ) return ;
826-
827- /* Build DELETE statement */
828- p = sql ;
829- s = "DELETE FROM \"" ;
830- while (* s ) * p ++ = * s ++ ;
831- s = tableName ;
832- while (* s ) * p ++ = * s ++ ;
833- s = "\" WHERE rowid = " ;
834- while (* s ) * p ++ = * s ++ ;
835- s = rowid ;
836- while (* s ) * p ++ = * s ++ ;
837- * p ++ = ';' ;
838- * p = '\0' ;
828+ /* Collect rowids first (data will be freed on re-query) */
829+ rowids = (char * * )LocalAlloc (LMEM_FIXED , count * sizeof (char * ));
830+ if (!rowids ) return ;
831+
832+ i = 0 ;
833+ sel = -1 ;
834+ while ((sel = ListView_GetNextItem (g_hwndGrid , sel , LVNI_SELECTED )) >= 0 ) {
835+ int j , len ;
836+ if (sel >= g_lastResultRows ) continue ;
837+ dataRow = g_sortIndex ? g_sortIndex [sel ] : sel ;
838+ rowidIdx = (dataRow + 1 ) * g_lastResultCols ;
839+ rowid = g_lastResult [rowidIdx ];
840+ if (rowid && i < count ) {
841+ len = 0 ;
842+ while (rowid [len ]) len ++ ;
843+ rowids [i ] = (char * )LocalAlloc (LMEM_FIXED , len + 1 );
844+ if (rowids [i ]) {
845+ for (j = 0 ; j <= len ; j ++ ) rowids [i ][j ] = rowid [j ];
846+ i ++ ;
847+ }
848+ }
849+ }
850+ count = i ; /* Actual count collected */
839851
840- /* Execute DELETE */
841- rc = sqlite_exec (g_db , sql , NULL , NULL , & errmsg );
852+ /* Delete by rowid */
853+ deleted = 0 ;
854+ for (i = 0 ; i < count ; i ++ ) {
855+ p = sql ;
856+ s = "DELETE FROM \"" ;
857+ while (* s ) * p ++ = * s ++ ;
858+ s = tableName ;
859+ while (* s ) * p ++ = * s ++ ;
860+ s = "\" WHERE rowid = " ;
861+ while (* s ) * p ++ = * s ++ ;
862+ s = rowids [i ];
863+ while (* s ) * p ++ = * s ++ ;
864+ * p ++ = ';' ;
865+ * p = '\0' ;
866+
867+ rc = sqlite_exec (g_db , sql , NULL , NULL , & errmsg );
868+ if (rc != SQLITE_OK ) {
869+ wchar_t wmsg [256 ];
870+ MultiByteToWideChar (CP_ACP , 0 , errmsg ? errmsg : "Unknown error" , -1 , wmsg , 256 );
871+ MessageBoxW (g_hwndMain , wmsg , L"Delete Failed" , MB_OK | MB_ICONERROR );
872+ if (errmsg ) sqlite_freemem (errmsg );
873+ break ;
874+ }
875+ deleted ++ ;
876+ }
842877
843- if (rc != SQLITE_OK ) {
844- wchar_t wmsg [256 ];
845- MultiByteToWideChar (CP_ACP , 0 , errmsg ? errmsg : "Unknown error" , -1 , wmsg , 256 );
846- MessageBoxW (g_hwndMain , wmsg , L"Delete Failed" , MB_OK | MB_ICONERROR );
847- if (errmsg ) sqlite_freemem (errmsg );
848- return ;
878+ /* Free rowid copies */
879+ for (i = 0 ; i < count ; i ++ ) {
880+ if (rowids [i ]) LocalFree (rowids [i ]);
849881 }
882+ LocalFree (rowids );
850883
851884 /* Re-query to refresh grid */
852885 OpenTableForEditing (tableName );
886+
887+ /* Status feedback */
888+ if (deleted > 0 ) {
889+ wsprintfW (msg , L"%d row%s deleted" , deleted , deleted == 1 ? L"" : L"s" );
890+ SendMessageW (g_hwndStatus , SB_SETTEXTW , 1 , (LPARAM )msg );
891+ }
853892}
854893
855894/*============================================================================
0 commit comments