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