You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

StyledMessageUtils.java 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package com.dmdirc.ui.messages;
  2. import javax.inject.Inject;
  3. import javax.inject.Singleton;
  4. import static com.dmdirc.ui.messages.Styliser.CODE_CHANNEL;
  5. import static com.dmdirc.ui.messages.Styliser.CODE_HYPERLINK;
  6. import static com.dmdirc.ui.messages.Styliser.CODE_NICKNAME;
  7. import static com.dmdirc.ui.messages.Styliser.CODE_SMILIE;
  8. import static com.dmdirc.ui.messages.Styliser.CODE_TOOLTIP;
  9. import static com.google.common.base.Preconditions.checkArgument;
  10. /**
  11. * Utilities for dealing with styled messages.
  12. */
  13. @Singleton
  14. public class StyledMessageUtils {
  15. @Inject
  16. public StyledMessageUtils() {
  17. }
  18. /**
  19. * Strips all recognised control codes from the input string.
  20. *
  21. * @param input the String to be stripped
  22. *
  23. * @return a copy of the input with control codes removed
  24. */
  25. public String stripControlCodes(final String input) {
  26. return input.replaceAll("[" + IRCControlCodes.BOLD + CODE_CHANNEL + IRCControlCodes.FIXED
  27. + CODE_HYPERLINK + IRCControlCodes.ITALIC + IRCControlCodes.NEGATE + CODE_NICKNAME
  28. + CODE_SMILIE + IRCControlCodes.STOP + IRCControlCodes.UNDERLINE + "]|"
  29. + IRCControlCodes.COLOUR_HEX + "([A-Za-z0-9]{6}(,[A-Za-z0-9]{6})?)?|"
  30. + IRCControlCodes.COLOUR + "([0-9]{1,2}(,[0-9]{1,2})?)?", "")
  31. .replaceAll(CODE_TOOLTIP + ".*?" + CODE_TOOLTIP + "(.*?)" + CODE_TOOLTIP, "$1");
  32. }
  33. /**
  34. * Retrieves the styled String contained within the unstyled offsets specified. That is, the
  35. * <code>from</code> and <code>to</code> arguments correspond to indexes in an unstyled version
  36. * of the <code>styled</code> string. The unstyled indices are translated to offsets within the
  37. * styled String, and the return value includes all text and control codes between those
  38. * indices.
  39. * <p>
  40. * The index translation is left-biased; that is, the indices are translated to be as far left
  41. * as they possibly can be. This means that the start of the string will include any control
  42. * codes immediately preceding the desired text, and the end will not include any trailing
  43. * codes.
  44. * <p>
  45. * This method will NOT include "internal" control codes in the output.
  46. *
  47. * @param styled The styled String to be operated on
  48. * @param from The starting index in the unstyled string
  49. * @param to The ending index in the unstyled string
  50. *
  51. * @return The corresponding text between the two indices
  52. */
  53. public String getStyledText(final String styled, final int from, final int to) {
  54. checkArgument(from < to, "'from' (" + from + ") must be less than 'to' (" + to + ')');
  55. checkArgument(from >= 0, "'from' (" + from + ") must be non-negative");
  56. final String unstyled = stripControlCodes(styled);
  57. checkArgument(to <= unstyled.length(), "'to' (" + to + ") must be less than or equal to "
  58. + "the unstyled length (" + unstyled.length() + ')');
  59. final String startBit = unstyled.substring(0, from);
  60. final String middleBit = unstyled.substring(from, to);
  61. final String sanitised = stripInternalControlCodes(styled);
  62. int start = from;
  63. while (!stripControlCodes(sanitised.substring(0, start)).equals(startBit)) {
  64. start++;
  65. }
  66. int end = to + start - from;
  67. while (!stripControlCodes(sanitised.substring(start, end)).equals(middleBit)) {
  68. end++;
  69. }
  70. return sanitised.substring(start, end);
  71. }
  72. /**
  73. * Strips all recognised internal control codes from the input string.
  74. *
  75. * @param input the String to be stripped
  76. *
  77. * @return a copy of the input with control codes removed
  78. */
  79. private String stripInternalControlCodes(final String input) {
  80. return input.replaceAll("[" + CODE_CHANNEL + CODE_HYPERLINK + CODE_NICKNAME
  81. + CODE_SMILIE + IRCControlCodes.STOP + IRCControlCodes.UNDERLINE + ']', "")
  82. .replaceAll(CODE_TOOLTIP + ".*?" + CODE_TOOLTIP + "(.*?)"
  83. + CODE_TOOLTIP, "$1");
  84. }
  85. }