diff --git a/programs/winecfg/drive.c b/programs/winecfg/drive.c index 40dc57460d3..726ac258e48 100644 --- a/programs/winecfg/drive.c +++ b/programs/winecfg/drive.c @@ -55,7 +55,7 @@ char *getDriveValue(char letter, char *valueName) { 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); @@ -74,7 +74,14 @@ end: 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); @@ -141,7 +148,7 @@ void initDriveDlg (HWND hDlg) 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++; @@ -149,6 +156,7 @@ void initDriveDlg (HWND hDlg) } WINE_TRACE("loaded %d drives\n", driveCount); + SendMessageA(GetDlgItem(hDlg, IDC_LIST_DRIVES), LB_SETSEL, TRUE, 0); free(subKeyName); updatingUI = FALSE; @@ -253,8 +261,8 @@ long drive_available_mask(char letter) } } - 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; @@ -329,10 +337,12 @@ void refreshDriveEditDialog(HWND hDlg) { 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 { @@ -347,7 +357,7 @@ void refreshDriveEditDialog(HWND hDlg) { } 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); @@ -355,12 +365,28 @@ void refreshDriveEditDialog(HWND hDlg) { 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; @@ -387,18 +413,47 @@ INT_PTR CALLBACK DriveEditDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM l } 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) @@ -414,9 +469,10 @@ DriveDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 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: @@ -443,7 +499,8 @@ DriveDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR); break; case PSN_SETACTIVE: - initDriveDlg (hDlg); + driveDlgHandle = hDlg; + refreshDriveDlg (driveDlgHandle); break; } break; diff --git a/programs/winecfg/winecfg.c b/programs/winecfg/winecfg.c index 4719e66164d..4b2fcf000cc 100644 --- a/programs/winecfg/winecfg.c +++ b/programs/winecfg/winecfg.c @@ -106,7 +106,7 @@ end: } /***************************************************************************** - * 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 @@ void addTransaction(char *section, char *key, enum transaction_action action, ch 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 @@ void addTransaction(char *section, char *key, enum transaction_action action, ch tqhead = trans; } - if (instantApply) processTransaction(trans); + if (instantApply) { + processTransaction(trans); + destroyTransaction(trans); + } } void processTransaction(struct transaction *trans) { @@ -239,11 +242,25 @@ void processTransaction(struct transaction *trans) { /* TODO: implement notifications here */ } -void processTransQueue() { +void processTransQueue(void) +{ 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 --git a/programs/winecfg/winecfg.h b/programs/winecfg/winecfg.h index 7bc36ddec57..a163bbef594 100644 --- a/programs/winecfg/winecfg.h +++ b/programs/winecfg/winecfg.h @@ -99,6 +99,9 @@ void saveDriveSettings (HWND hDlg); 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 WINE_KEY_ROOT "Software\\Wine\\WineCfg\\Config" #endif