SendTextView.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #include <iostream>
  2. /*
  3. * Copyright 2021, Jaidyn Levesque <jadedctrl@teknik.io>
  4. * All rights reserved. Distributed under the terms of the MIT license.
  5. */
  6. #include "SendTextView.h"
  7. #include <StringList.h>
  8. #include <Window.h>
  9. #include "AppMessages.h"
  10. #include "MainWindow.h"
  11. #include "Server.h"
  12. #include "TheApp.h"
  13. SendTextView::SendTextView(const char* name, ConversationView* convView)
  14. :
  15. BTextView(name),
  16. fChatView(convView),
  17. fCurrentIndex(0),
  18. fHistoryIndex(0)
  19. {
  20. }
  21. void
  22. SendTextView::KeyDown(const char* bytes, int32 numBytes)
  23. {
  24. int32 modifiers = Window()->CurrentMessage()->GetInt32("modifiers", 0);
  25. if (bytes[0] == B_TAB) {
  26. _AutoComplete();
  27. return;
  28. }
  29. // Reset auto-complete state if user typed/sent something other than tab
  30. fCurrentIndex = 0;
  31. fCurrentWord.SetTo("");
  32. if ((bytes[0] == B_UP_ARROW) && (modifiers == 0)) {
  33. _UpHistory();
  34. return;
  35. }
  36. else if ((bytes[0] == B_DOWN_ARROW) && (modifiers == 0)) {
  37. _DownHistory();
  38. return;
  39. }
  40. if ((bytes[0] == B_ENTER) && (modifiers & B_COMMAND_KEY))
  41. Insert("\n");
  42. else if ((bytes[0] == B_ENTER) && (modifiers == 0)) {
  43. _AppendHistory();
  44. fChatView->MessageReceived(new BMessage(APP_CHAT));
  45. }
  46. else
  47. BTextView::KeyDown(bytes, numBytes);
  48. }
  49. void
  50. SendTextView::_AutoComplete()
  51. {
  52. if (fChatView == NULL || fChatView->GetConversation() == NULL)
  53. return;
  54. BStringList words;
  55. BString text = Text();
  56. text.Split(" ", true, words);
  57. if (words.CountStrings() <= 0)
  58. return;
  59. BString lastWord = words.StringAt(words.CountStrings() - 1);
  60. if (fCurrentWord.IsEmpty() == true)
  61. fCurrentWord = lastWord;
  62. // Now to find the substitutes
  63. BString substitution;
  64. if (fCurrentWord.StartsWith("/") == true) {
  65. substitution =
  66. _NextMatch(_CommandNames(), BString(fCurrentWord).RemoveFirst("/"));
  67. if (substitution.IsEmpty() == false)
  68. substitution.Prepend("/");
  69. }
  70. else
  71. substitution = _NextMatch(_UserNames(), fCurrentWord);
  72. // Apply the substitution or jet off
  73. if (substitution.IsEmpty() == true)
  74. fCurrentIndex = 0;
  75. else {
  76. int32 index = text.FindLast(lastWord);
  77. int32 newindex = index + substitution.Length();
  78. Delete(index, index + lastWord.CountChars());
  79. Insert(index, substitution, substitution.Length());
  80. Select(newindex, newindex);
  81. }
  82. }
  83. BString
  84. SendTextView::_NextMatch(BStringList list, BString current)
  85. {
  86. BString match;
  87. for (int i = 0, j = 0; i < list.CountStrings(); i++)
  88. if (list.StringAt(i).StartsWith(current)) {
  89. if (j == fCurrentIndex) {
  90. match = list.StringAt(i);
  91. fCurrentIndex++;
  92. break;
  93. }
  94. j++;
  95. }
  96. return match;
  97. }
  98. BStringList
  99. SendTextView::_CommandNames()
  100. {
  101. if (fCurrentIndex == 0) {
  102. int64 instance = fChatView->GetConversation()->GetProtocolLooper()->GetInstance();
  103. BStringList cmdNames;
  104. CommandMap cmds =
  105. ((TheApp*)be_app)->GetMainWindow()->GetServer()->Commands(instance);
  106. for (int i = 0; i < cmds.CountItems(); i++)
  107. cmdNames.Add(cmds.KeyAt(i));
  108. fCurrentList = cmdNames;
  109. }
  110. return fCurrentList;
  111. }
  112. BStringList
  113. SendTextView::_UserNames()
  114. {
  115. if (fCurrentIndex == 0) {
  116. BStringList nameAndId;
  117. UserMap users = fChatView->GetConversation()->Users();
  118. for (int i = 0; i < users.CountItems(); i++) {
  119. nameAndId.Add(users.KeyAt(i));
  120. nameAndId.Add(users.ValueAt(i)->GetName());
  121. }
  122. fCurrentList = nameAndId;
  123. }
  124. return fCurrentList;
  125. }
  126. void
  127. SendTextView::_AppendHistory()
  128. {
  129. fHistoryIndex = 0;
  130. fHistory.Add(BString(Text()), 0);
  131. if (fHistory.CountStrings() == 21)
  132. fHistory.Remove(20);
  133. }
  134. void
  135. SendTextView::_UpHistory()
  136. {
  137. if (fHistoryIndex == 0 && TextLength() > 0)
  138. _AppendHistory();
  139. if (fHistoryIndex < fHistory.CountStrings()) {
  140. fHistoryIndex++;
  141. SetText(fHistory.StringAt(fHistoryIndex - 1));
  142. Select(TextLength(), TextLength());
  143. }
  144. }
  145. void
  146. SendTextView::_DownHistory()
  147. {
  148. if (fHistoryIndex > 1) {
  149. fHistoryIndex--;
  150. SetText(fHistory.StringAt(fHistoryIndex - 1));
  151. Select(TextLength(), TextLength());
  152. }
  153. }