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 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. * Copyright (c) 2006-2017 DMDirc Developers
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  5. * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
  7. * permit persons to whom the Software is furnished to do so, subject to the following conditions:
  8. *
  9. * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
  10. * Software.
  11. *
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  13. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
  14. * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  15. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  16. */
  17. package com.dmdirc.ui.messages;
  18. import javax.inject.Inject;
  19. import javax.inject.Singleton;
  20. import static com.dmdirc.ui.messages.Styliser.CODE_CHANNEL;
  21. import static com.dmdirc.ui.messages.Styliser.CODE_HYPERLINK;
  22. import static com.dmdirc.ui.messages.Styliser.CODE_NICKNAME;
  23. import static com.dmdirc.ui.messages.Styliser.CODE_SMILIE;
  24. import static com.dmdirc.ui.messages.Styliser.CODE_TOOLTIP;
  25. import static com.google.common.base.Preconditions.checkArgument;
  26. /**
  27. * Utilities for dealing with styled messages.
  28. */
  29. @Singleton
  30. public class StyledMessageUtils {
  31. @Inject
  32. public StyledMessageUtils() {
  33. }
  34. /**
  35. * Strips all recognised control codes from the input string.
  36. *
  37. * @param input the String to be stripped
  38. *
  39. * @return a copy of the input with control codes removed
  40. */
  41. public String stripControlCodes(final String input) {
  42. return input.replaceAll("[" + IRCControlCodes.BOLD + CODE_CHANNEL + IRCControlCodes.FIXED
  43. + CODE_HYPERLINK + IRCControlCodes.ITALIC + IRCControlCodes.NEGATE
  44. + CODE_SMILIE + IRCControlCodes.STOP + IRCControlCodes.UNDERLINE + "]|"
  45. + IRCControlCodes.COLOUR_HEX + "([A-Za-z0-9]{6}(,[A-Za-z0-9]{6})?)?|"
  46. + IRCControlCodes.COLOUR + "([0-9]{1,2}(,[0-9]{1,2})?)?", "")
  47. .replaceAll("([" + CODE_TOOLTIP + CODE_NICKNAME + "]).*?\\1(.*?)\\1", "$2");
  48. }
  49. /**
  50. * Retrieves the styled String contained within the unstyled offsets specified. That is, the
  51. * <code>from</code> and <code>to</code> arguments correspond to indexes in an unstyled version
  52. * of the <code>styled</code> string. The unstyled indices are translated to offsets within the
  53. * styled String, and the return value includes all text and control codes between those
  54. * indices.
  55. * <p>
  56. * The index translation is left-biased; that is, the indices are translated to be as far left
  57. * as they possibly can be. This means that the start of the string will include any control
  58. * codes immediately preceding the desired text, and the end will not include any trailing
  59. * codes.
  60. * <p>
  61. * This method will NOT include "internal" control codes in the output.
  62. *
  63. * @param styled The styled String to be operated on
  64. * @param from The starting index in the unstyled string
  65. * @param to The ending index in the unstyled string
  66. *
  67. * @return The corresponding text between the two indices
  68. */
  69. public String getStyledText(final String styled, final int from, final int to) {
  70. checkArgument(from < to, "'from' (" + from + ") must be less than 'to' (" + to + ')');
  71. checkArgument(from >= 0, "'from' (" + from + ") must be non-negative");
  72. final String unstyled = stripControlCodes(styled);
  73. checkArgument(to <= unstyled.length(), "'to' (" + to + ") must be less than or equal to "
  74. + "the unstyled length (" + unstyled.length() + ')');
  75. final String startBit = unstyled.substring(0, from);
  76. final String middleBit = unstyled.substring(from, to);
  77. final String sanitised = stripInternalControlCodes(styled);
  78. int start = from;
  79. while (!stripControlCodes(sanitised.substring(0, start)).equals(startBit)) {
  80. start++;
  81. }
  82. int end = to + start - from;
  83. while (!stripControlCodes(sanitised.substring(start, end)).equals(middleBit)) {
  84. end++;
  85. }
  86. return sanitised.substring(start, end);
  87. }
  88. /**
  89. * Strips all recognised internal control codes from the input string.
  90. *
  91. * @param input the String to be stripped
  92. *
  93. * @return a copy of the input with control codes removed
  94. */
  95. private String stripInternalControlCodes(final String input) {
  96. return input.replaceAll("[" + CODE_CHANNEL + CODE_HYPERLINK + CODE_SMILIE + ']', "")
  97. .replaceAll("([" + CODE_TOOLTIP + CODE_NICKNAME + "]).*?\\1(.*?)\\1", "$2");
  98. }
  99. }