Index: mptrack/PatternEditorDialogs.cpp
===================================================================
--- mptrack/PatternEditorDialogs.cpp	(revision 12048)
+++ mptrack/PatternEditorDialogs.cpp	(working copy)
@@ -880,7 +880,7 @@
 	CMainFrame *pMainFrm;
 
 	CDialog::OnInitDialog();
-	m_Keyboard.Init(m_hWnd, 2);
+	m_Keyboard.Init(m_hWnd, 4);
 	pMainFrm = CMainFrame::GetMainFrame();
 	if (!pMainFrm) return TRUE;
 	// Fills the shortcut key combo box
@@ -891,22 +891,25 @@
 	m_CbnBaseNote.SetItemData(m_CbnBaseNote.AddString(_T("Relative")), MPTChord::relativeMode);
 	AppendNotesToControl(m_CbnBaseNote, NOTE_MIN, NOTE_MIN + 3 * 12 - 1);
 
-	// Minor notes
+	// Chord Factor combo boxes
 	CString s;
-	for (int inotes=-1; inotes<24; inotes++)
+	for (int inotes = -25; inotes < 24; inotes++)
 	{
-		if(inotes < 0)
+		if(inotes == -25)
 		{
 			s = _T("--");
+		} else if(inotes >= 0)
+		{
+			s = mpt::ToCString(CSoundFile::GetDefaultNoteName(inotes % 12));
+			if(inotes >= 12) s.AppendFormat(_T(" (+%d)"), inotes / 12);
 		} else
 		{
-			s = mpt::ToCString(CSoundFile::GetDefaultNoteName(inotes % 12));
-			if(inotes >= 12)
-				s.AppendFormat(_T(" (+%d)"), inotes / 12);
+			s = mpt::ToCString(CSoundFile::GetDefaultNoteName((24 + inotes) % 12));
+			s.AppendFormat(_T(" (-%d)"), (11 - inotes) / 12);
 		}
-		m_CbnNote1.AddString(s);
-		m_CbnNote2.AddString(s);
-		m_CbnNote3.AddString(s);
+		m_CbnNote1.SetItemData(m_CbnNote1.AddString(s), inotes);
+		m_CbnNote2.SetItemData(m_CbnNote2.AddString(s), inotes);
+		m_CbnNote3.SetItemData(m_CbnNote3.AddString(s), inotes);
 	}
 	// Update Dialog
 	OnChordChanged();
@@ -928,47 +931,67 @@
 {
 	if (wParam != KBDNOTIFY_LBUTTONDOWN) return 0;
 	MPTChord &chord = GetChord();
-	UINT cnote = NOTE_NONE;
-	chord.notes[0] = NOTE_NONE;
-	chord.notes[1] = NOTE_NONE;
-	chord.notes[2] = NOTE_NONE;
-	for(UINT i = 0; i < 2 * 12; i++)
+	int8 newKey = 1 + -2 * 12 + (int8)nKey;
+	//NOTE_NONE is zero, so "C-" or "root note" uses ZERO_SURROGATE.
+	newKey = (newKey == NOTE_NONE) ? ZERO_SURROGATE : newKey;
+
+	//Clear note.
+	for(UINT i = 0; i + 1 < MPTChord::notesPerChord; i++)
 	{
-		if(chord.key == MPTChord::relativeMode)
+		if(chord.notes[i] == newKey)
 		{
-			if(!i) continue;
-		} else
-		{
-			if(i == chord.key % 12u) continue;
+			for(UINT j = i; j + 1 < MPTChord::notesPerChord; j++)
+			{
+				chord.notes[j] = (j + 2 < MPTChord::notesPerChord) ? chord.notes[j + 1] : NOTE_NONE;
+			}
+			OnChordChanged();
+			return 0;
 		}
+	}
 
-		UINT n = m_Keyboard.GetFlags(i);
-		if (i == (UINT)nKey) n = (n) ? 0 : 1;
-		if (n)
+	//Add note.
+	for(UINT i = 0; i + 1 < MPTChord::notesPerChord; i++)
+	{
+		if(chord.notes[i] == NOTE_NONE || i + 2 >= MPTChord::notesPerChord)
 		{
-			if ((cnote < 3) || (i == (UINT)nKey))
-			{
-				UINT k = (cnote < 3) ? cnote : 2;
-				chord.notes[k] = static_cast<BYTE>(i+1);
-				if (cnote < 3) cnote++;
-			}
+			chord.notes[i] = newKey;
+			OnChordChanged();
+			return 0;
 		}
 	}
-	OnChordChanged();
-	return 0;
+
+	//Do nothing.
+	return 1;
 }
 
 
 void CChordEditor::OnChordChanged()
 {
+	int8 tempChord[3];  //scratch copy of chord.notes
 	MPTChord &chord = GetChord();
 	if(chord.key != MPTChord::relativeMode)
 		m_CbnBaseNote.SetCurSel(chord.key + 1);
 	else
 		m_CbnBaseNote.SetCurSel(0);
-	m_CbnNote1.SetCurSel(chord.notes[0]);
-	m_CbnNote2.SetCurSel(chord.notes[1]);
-	m_CbnNote3.SetCurSel(chord.notes[2]);
+	for (UINT i = 0; i + 1 < MPTChord::notesPerChord; i++)
+	{
+		tempChord[i] = chord.notes[i];
+		if(tempChord[i] == ZERO_SURROGATE)
+		{
+			tempChord[i] = 2 * 12;
+		}
+		else if (tempChord[i] == 0)
+		{
+			tempChord[i] = 0;
+		}
+		else
+		{
+			tempChord[i] += 2 * 12;
+		}
+	}
+	m_CbnNote1.SetCurSel(tempChord[0]);
+	m_CbnNote2.SetCurSel(tempChord[1]);
+	m_CbnNote3.SetCurSel(tempChord[2]);
 	UpdateKeyboard();
 }
 
@@ -981,15 +1004,26 @@
 	{
 		note = 0;
 	}
-	for(UINT i = 0; i < 2 * 12; i++)
+	for(INT i = -2 * 12; i < 2 * 12; i++)
 	{
 		uint8 b = CKeyboardControl::KEYFLAG_NORMAL;
-		if(i == note) b = CKeyboardControl::KEYFLAG_REDDOT;
-		else if(chord.notes[0] && i + 1 == chord.notes[0]) b = CKeyboardControl::KEYFLAG_REDDOT;
-		else if(chord.notes[1] && i + 1 == chord.notes[1]) b = CKeyboardControl::KEYFLAG_REDDOT;
-		else if(chord.notes[2] && i + 1 == chord.notes[2]) b = CKeyboardControl::KEYFLAG_REDDOT;
-		m_Keyboard.SetFlags(i, b);
+		if(i + 1 && i + 1 == chord.notes[0])
+			b = CKeyboardControl::KEYFLAG_REDDOT;
+		else if(i + 1 && i + 1 == chord.notes[1])
+			b = CKeyboardControl::KEYFLAG_REDDOT;
+		else if(i + 1 && i + 1 == chord.notes[2])
+			b = CKeyboardControl::KEYFLAG_REDDOT;
+		else if(i == (INT)note)
+			b = CKeyboardControl::KEYFLAG_BRIGHTDOT;
+		m_Keyboard.SetFlags(i + 2 * 12, b);
 	}
+	for(UINT i = 0; i + 1 < MPTChord::notesPerChord; i++)
+	{
+		if(chord.notes[i] == ZERO_SURROGATE)
+		{
+			m_Keyboard.SetFlags(2 * 12 - 1, CKeyboardControl::KEYFLAG_REDDOT);
+		}
+	}	
 	m_Keyboard.InvalidateRect(NULL, FALSE);
 }
 
@@ -1009,11 +1043,18 @@
 {
 	MPTChord &chord = GetChord();
 	int note = m_CbnNote1.GetCurSel();
-	if(note >= 0)
+	if(note < 0)
+		return;
+	if(note == 2 * 12)
 	{
-		chord.notes[0] = (uint8)note;
-		UpdateKeyboard();
+		note = ZERO_SURROGATE;
 	}
+	else if (note)
+	{
+		note -= 2 * 12;
+	}
+	chord.notes[0] = (int8)note;
+	UpdateKeyboard();
 }
 
 
@@ -1021,11 +1062,17 @@
 {
 	MPTChord &chord = GetChord();
 	int note = m_CbnNote2.GetCurSel();
-	if(note >= 0)
+	if(note < 0)
+		return;
+	if(note == 2 * 12)
 	{
-		chord.notes[1] = (uint8)note;
-		UpdateKeyboard();
+		note = ZERO_SURROGATE;
+	} else if(note)
+	{
+		note -= 2 * 12;
 	}
+	chord.notes[1] = (int8)note;
+	UpdateKeyboard();
 }
 
 
@@ -1033,11 +1080,17 @@
 {
 	MPTChord &chord = GetChord();
 	int note = m_CbnNote3.GetCurSel();
-	if(note >= 0)
+	if(note < 0)
+		return;
+	if(note == 2 * 12)
 	{
-		chord.notes[2] = (uint8)note;
-		UpdateKeyboard();
+		note = ZERO_SURROGATE;
+	} else if(note)
+	{
+		note -= 2 * 12;
 	}
+	chord.notes[2] = (int8)note;
+	UpdateKeyboard();
 }
 
 
Index: mptrack/PatternEditorDialogs.h
===================================================================
--- mptrack/PatternEditorDialogs.h	(revision 12048)
+++ mptrack/PatternEditorDialogs.h	(working copy)
@@ -108,6 +108,13 @@
 
 class CChordEditor: public CDialog
 {
+
+public:
+	enum
+	{
+		ZERO_SURROGATE = 0x3E
+	};
+
 protected:
 	CKeyboardControl m_Keyboard;
 	CComboBox m_CbnShortcut, m_CbnBaseNote, m_CbnNote1, m_CbnNote2, m_CbnNote3;
Index: mptrack/TrackerSettings.cpp
===================================================================
--- mptrack/TrackerSettings.cpp	(revision 12048)
+++ mptrack/TrackerSettings.cpp	(working copy)
@@ -393,15 +393,15 @@
 		if(ichord < 12)
 		{
 			// Major Chords
-			Chords[ichord].notes[0] = (uint8)(ichord+5);
-			Chords[ichord].notes[1] = (uint8)(ichord+8);
-			Chords[ichord].notes[2] = (uint8)(ichord+11);
+			Chords[ichord].notes[0] = (int8)(ichord+5);
+			Chords[ichord].notes[1] = (int8)(ichord+8);
+			Chords[ichord].notes[2] = (int8)(ichord+11);
 		} else if(ichord < 24)
 		{
 			// Minor Chords
-			Chords[ichord].notes[0] = (uint8)(ichord-8);
-			Chords[ichord].notes[1] = (uint8)(ichord-4);
-			Chords[ichord].notes[2] = (uint8)(ichord-1);
+			Chords[ichord].notes[0] = (int8)(ichord-8);
+			Chords[ichord].notes[1] = (int8)(ichord-4);
+			Chords[ichord].notes[2] = (int8)(ichord-1);
 		}
 	}
 
@@ -1238,9 +1238,9 @@
 			if((chord & 0xFFFFFFC0) || (!chords[i].notes[0]))
 			{
 				chords[i].key = (uint8)(chord & 0x3F);
-				chords[i].notes[0] = (uint8)((chord >> 6) & 0x3F);
-				chords[i].notes[1] = (uint8)((chord >> 12) & 0x3F);
-				chords[i].notes[2] = (uint8)((chord >> 18) & 0x3F);
+				chords[i].notes[0] = static_cast<int8>(((chord >> 6) & 0x3F) | (0xC0 * ((chord >> 11) & 1)));
+				chords[i].notes[1] = static_cast<int8>(((chord >> 12) & 0x3F) | (0xC0 * ((chord >> 17) & 1)));
+				chords[i].notes[2] = static_cast<int8>(((chord >> 18) & 0x3F) | (0xC0 * ((chord >> 23) & 1)));
 			}
 		}
 	}
@@ -1251,7 +1251,7 @@
 {
 	for(std::size_t i = 0; i < std::size(chords); i++)
 	{
-		int32 s = (chords[i].key) | (chords[i].notes[0] << 6) | (chords[i].notes[1] << 12) | (chords[i].notes[2] << 18);
+		int32 s = (chords[i].key) | ((chords[i].notes[0] & 0x3F) << 6) | ((chords[i].notes[1] & 0x3F) << 12) | ((chords[i].notes[2] & 0x3F) << 18);
 		mpt::ustring note = mpt::format(U_("%1%2"))(mpt::ustring(NoteNamesSharp[i % 12]), i / 12);
 		conf.Write<int32>(U_("Chords"), note, s);
 	}
Index: mptrack/TrackerSettings.h
===================================================================
--- mptrack/TrackerSettings.h	(revision 12048)
+++ mptrack/TrackerSettings.h	(working copy)
@@ -193,7 +193,7 @@
 	};
 
 	uint8 key;			// Base note
-	uint8 notes[3];		// Additional chord notes
+	int8 notes[3];		// Additional chord notes
 };
 
 using MPTChords = std::array<MPTChord, 3 * 12>;	// 3 octaves
Index: mptrack/View_pat.cpp
===================================================================
--- mptrack/View_pat.cpp	(revision 12048)
+++ mptrack/View_pat.cpp	(working copy)
@@ -5193,18 +5193,18 @@
 
 	for(auto cnote : chord.notes)
 	{
-		if(cnote)
+		if(cnote) //Check for NOTE_NONE
 		{
-			ModCommand::NOTE chordNote = key - NOTE_MIN;
+			int32 chordNote = key - NOTE_MIN;
 			if(!relativeMode)
 			{
 				// Only use octave information from the base key
 				chordNote = (chordNote / 12) * 12;
 			}
-			chordNote += cnote;
-			if(specs.HasNote(chordNote))
+			chordNote += (cnote == CChordEditor::ZERO_SURROGATE) ? 0 : (int32)cnote;
+			if(chordNote >= NOTE_MIN && chordNote <= NOTE_MAX && specs.HasNote(static_cast<ModCommand::NOTE>(chordNote)))
 			{
-				outNotes[numNotes++] = chordNote;
+				outNotes[numNotes++] = static_cast<ModCommand::NOTE>(chordNote);
 			}
 		}
 	}
