[winecfg 7] Bugfixes, implement add drive, partly reactive drive edit dialog

Mike Hearn mike at theoretic.com
Sun Sep 7 11:11:41 CDT 2003


ChangeLog:
- Bugfixes to the transaction system
- Better protection against incomplete config sections
- Implement "Add Drive"
- Partly reactivate edit drive dialog

Only in programs/winecfg: config.log
diff -ur --exclude-from=diff-exclusions ../head/programs/winecfg/drive.c programs/winecfg/drive.c
--- ../head/programs/winecfg/drive.c	2003-09-05 22:55:02.000000000 +0100
+++ programs/winecfg/drive.c	2003-09-07 16:12:34.000000000 +0100
@@ -50,7 +50,7 @@
   
   WINE_TRACE("letter=%c, valueName=%s\n", letter, valueName);
 
-  subKeyName = malloc(strlen("Drive X"));
+  subKeyName = malloc(strlen("Drive X")+1);
   sprintf(subKeyName, "Drive %c", letter);
 
   hr = RegOpenKeyEx(configKey, subKeyName, 0, KEY_READ, &hkDrive);
@@ -69,7 +69,14 @@
   return result;
 }
 
-void initDriveDlg (HWND hDlg)
+void setDriveValue(char letter, char *valueName, char *newValue) {
+  char *driveSection = malloc(strlen("Drive X")+1);
+  sprintf(driveSection, "Drive %c", letter);
+  addTransaction(driveSection, valueName, ACTION_SET, newValue);
+  free(driveSection);
+}
+
+void refreshDriveDlg (HWND hDlg)
 {
   int i;
   char *subKeyName = malloc(MAX_NAME_LENGTH);
@@ -136,7 +143,7 @@
       SendMessageA(GetDlgItem(hDlg, IDC_LIST_DRIVES), LB_SETITEMDATA, itemIndex, (LPARAM) driveLetter);
       
       free(title);
-      free(label);
+      if (label && (strcmp(label, "no label") != 0)) free(label);
 
       driveCount++;
 	
@@ -144,6 +151,7 @@
   }
   
   WINE_TRACE("loaded %d drives\n", driveCount);
+  SendMessageA(GetDlgItem(hDlg, IDC_LIST_DRIVES), LB_SETSEL, TRUE, 0);
   
   free(subKeyName);  
   updatingUI = FALSE;
@@ -248,8 +256,8 @@
     }
   }
   
-  result = ~result; 
-  result |= DRIVE_MASK_BIT(letter);
+  result = ~result;
+  if (letter) result |= DRIVE_MASK_BIT(letter);
   
   WINE_TRACE( "finished drive letter loop with %lx\n", result );
   return result;
@@ -324,10 +332,12 @@
     SendDlgItemMessage(hDlg, IDC_EDIT_DEVICE, WM_SETTEXT, 0,(LPARAM)device);
   } else WINE_WARN("no Device field?\n");
 
-  if( strcmp("cdrom", type) == 0 ||
-      strcmp("floppy", type) == 0) {
-    if( (strlen( device ) == 0) &&
-	((strlen( serial ) > 0) || (strlen( label ) > 0)) ) {
+  selection = IDC_RADIO_ASSIGN;
+  if ((type && strcmp("cdrom", type) == 0) ||
+      (type && strcmp("floppy", type) == 0)) {
+    
+    if( (type && (strlen( device ) == 0)) &&
+	((serial && strlen( serial ) > 0) || (label && strlen( label ) > 0)) ) {
       selection = IDC_RADIO_ASSIGN;
     }
     else {
@@ -342,7 +352,7 @@
   }
 
   CheckRadioButton( hDlg, IDC_RADIO_AUTODETECT, IDC_RADIO_ASSIGN, selection );
-  SendDlgItemMessage(hDlg, IDC_EDIT_PATH, WM_SETTEXT, 0,(LPARAM)path);
+  if (path) SendDlgItemMessage(hDlg, IDC_EDIT_PATH, WM_SETTEXT, 0,(LPARAM)path);
   
   if (path) free(path);
   if (type) free(type);
@@ -350,12 +360,28 @@
   if (serial) free(serial);
   if (label) free(label);
   if (device) free(device);
-  
+
   updatingUI = FALSE;
   
   return;
 }
 
+/* storing the drive propsheet HWND here is a bit ugly, but the simplest solution for now */
+static HWND driveDlgHandle;
+
+void onEditChanged(HWND hDlg, WORD controlID) {
+  WINE_TRACE("controlID=%d\n", controlID);
+  switch (controlID) {
+      case IDC_EDIT_LABEL: { /* drive label edit box */
+        char *label = getDialogItemText(hDlg, controlID);
+        setDriveValue(editWindowLetter, "Label", label);
+        refreshDriveDlg(driveDlgHandle);
+        free(label);
+        break;
+      }
+  }
+}
+
 INT_PTR CALLBACK DriveEditDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
   int selection;
@@ -382,18 +408,47 @@
 	    }
 	    break;
 	    
-	  case ID_BUTTON_OK: break;
-	  
-	  /* Fall through. */
-	  
+	  case ID_BUTTON_OK:	  
 	  case ID_BUTTON_CANCEL:
 	    EndDialog(hDlg, wParam);
 	    return TRUE;
       }
+      if (HIWORD(wParam) == EN_CHANGE) onEditChanged(hDlg, LOWORD(wParam));
+      break;
   }
   return FALSE;
 }
 
+void onAddDriveClicked(HWND hDlg) {
+  /* we should allocate a drive letter automatically. We also need some way to let the user choose the mapping point,
+     for now we will just force them to enter a path automatically, with / being the default. In future we should
+     be able to temporarily map / then invoke the directory chooser dialog. */
+  
+  char newLetter = 'D'; /* we skip A, B and of course C is already mapped, right? */
+  long mask = ~drive_available_mask(0); /* the mask is now which drives aren't available */
+  char *sectionName;
+  
+  while (mask & (1 << (newLetter - 'A'))) {
+    newLetter++;
+    if (newLetter > 'Z') {
+      MessageBox(NULL, "You cannot add any more drives.\n\nEach drive must have a letter, from A to Z, so you cannot have more than 26", "", MB_OK | MB_ICONEXCLAMATION);
+      return;
+    }
+  }
+  WINE_TRACE("allocating drive letter %c\n", newLetter);
+  
+  sectionName = malloc(strlen("Drive X") + 1);
+  sprintf(sectionName, "Drive %c", newLetter);
+  addTransaction(sectionName, "Path", ACTION_SET, "/"); /* default to root path */
+  addTransaction(sectionName, "Type", ACTION_SET, "hd");
+  processTransQueue(); /* make sure the drive has been added, even if we are not in instant apply mode */
+  free(sectionName);
+
+  refreshDriveDlg(driveDlgHandle);
+
+  DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DRIVE_EDIT2), NULL, (DLGPROC) DriveEditDlgProc, (LPARAM) newLetter);
+}
+
 
 INT_PTR CALLBACK
 DriveDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
@@ -409,9 +464,10 @@
 		    selection = -1;
 		    break;
 	      }
+	      break;
 
 	    case IDC_BUTTON_ADD:
-	      /* temporarily disabled, awaiting rewrite for transactional design (need to fill in defaults smartly, wizard?) */
+	      onAddDriveClicked(hDlg);
 	      break;
 
 	    case IDC_BUTTON_REMOVE:
@@ -438,7 +494,8 @@
 	      SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
 	      break;
 	    case PSN_SETACTIVE:
-	      initDriveDlg (hDlg);
+	      driveDlgHandle = hDlg;
+	      refreshDriveDlg (driveDlgHandle);
 	      break;
 	}
 	break;
Only in programs/winecfg: drive.c.old
Only in programs/winecfg: drive-mappings
Only in programs/winecfg: programs
diff -ur --exclude-from=diff-exclusions ../head/programs/winecfg/winecfg.c programs/winecfg/winecfg.c
--- ../head/programs/winecfg/winecfg.c	2003-09-05 22:55:02.000000000 +0100
+++ programs/winecfg/winecfg.c	2003-09-07 15:44:59.000000000 +0100
@@ -106,7 +106,7 @@
 }
 
 /*****************************************************************************
- * setConfigValue : Sets a configuration key in the registry
+ * setConfigValue : Sets a configuration key in the registry. Section will be created if it doesn't already exist
  *
  * HKEY  hCurrent : the registry key that the configuration is rooted at
  * char *subKey : the name of the config section
@@ -209,9 +209,9 @@
     assert( key != NULL );
     if (action == ACTION_SET) assert( newValue != NULL );
 
-    trans->section = section;
-    trans->key = key;
-    trans->newValue = newValue;
+    trans->section = strdup(section);
+    trans->key = strdup(key);
+    trans->newValue = strdup(newValue);
     trans->action = action;
     trans->next = NULL;
     trans->prev = NULL;
@@ -225,7 +225,10 @@
 	tqhead = trans;
     }
 
-    if (instantApply) processTransaction(trans);
+    if (instantApply) {
+	processTransaction(trans);
+	destroyTransaction(trans);
+    }
 }
 
 void processTransaction(struct transaction *trans) {
@@ -235,16 +238,28 @@
     } else if (trans->action == ACTION_REMOVE) {
 	WINE_TRACE("Removing %s\\%s", trans->section, trans->key);
 	removeConfigValue(trans->section, trans->key);
-    }
+    }    
     /* TODO: implement notifications here */
 }
 
 void processTransQueue() {
     WINE_TRACE("\n");
-    while (tqhead != NULL) {
-	processTransaction(tqhead);
-	tqhead = tqhead->next;
-	destroyTransaction(tqhead->prev);
+    while (tqtail != NULL) {
+	struct transaction *next = tqtail->next;
+	processTransaction(tqtail);
+	destroyTransaction(tqtail);
+	tqtail = next;	
     }
 }
 
+
+/* ================================== utility functions ============================ */
+
+/* returns a string with the window text of the dialog item. user is responsible for freeing the result */
+char *getDialogItemText(HWND hDlg, WORD controlID) {
+    HWND item = GetDlgItem(hDlg, controlID);
+    int len = GetWindowTextLength(item) + 1;
+    char *result = malloc(len);
+    if (GetWindowText(item, result, len) == 0) return NULL;
+    return result;
+}
diff -ur --exclude-from=diff-exclusions ../head/programs/winecfg/winecfg.h programs/winecfg/winecfg.h
--- ../head/programs/winecfg/winecfg.h	2003-09-05 22:55:02.000000000 +0100
+++ programs/winecfg/winecfg.h	2003-09-07 15:15:03.000000000 +0100
@@ -92,6 +92,10 @@
 INT_PTR CALLBACK DriveDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 INT_PTR CALLBACK DriveEditDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
 
+
+/* some basic utilities to make win32 suck less */
+char *getDialogItemText(HWND hDlg, WORD controlID);
+
 #define WINEHQ_KEY_ROOT "Software\\Wine\\WineCfg\\Config"
 
 #endif
 




More information about the wine-patches mailing list