BufferLine.swift 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. //
  2. // BufferLine.swift
  3. // SwiftTerm
  4. //
  5. // Created by Miguel de Icaza on 3/26/19.
  6. // Copyright © 2019 Miguel de Icaza. All rights reserved.
  7. //
  8. import Foundation
  9. class BufferLine: CustomDebugStringConvertible{
  10. var isWrapped: Bool
  11. var data: [CharData]
  12. public init (cols: Int, fillData: CharData? = nil, isWrapped: Bool = false)
  13. {
  14. let fill = (fillData == nil) ? CharData.Null : fillData!
  15. data = Array.init(repeating: fill, count: cols)
  16. self.isWrapped = isWrapped
  17. }
  18. public init (from other: BufferLine)
  19. {
  20. data = other.data
  21. isWrapped = other.isWrapped
  22. }
  23. public var count: Int {
  24. get {
  25. return data.count
  26. }
  27. }
  28. public subscript (index : Int /*, callingMethod: String = #function */) -> CharData {
  29. get {
  30. // The x value in a buffer can point beyond the column, due to the way that we allow
  31. // buffer.x to grow (this is to support some wrapmodes and write on the edge)
  32. if index >= data.count {
  33. /* print ("Warning: the method \(callingMethod) has not been audited to clamp buffer.x to cols-1; fixing") */
  34. return data [data.count-1]
  35. }
  36. return data [index]
  37. }
  38. set(value) {
  39. if index >= data.count {
  40. /* print ("Warning: the method \(callingMethod) has not been audited to clamp buffer.x to cols-1; fixing") */
  41. data [data.count-1] = value
  42. }
  43. data [index] = value
  44. }
  45. }
  46. public func getWidth (index: Int) -> Int {
  47. return Int (data [index].width)
  48. }
  49. /// Test whether contains any chars.
  50. public func hasContent (index: Int) -> Bool {
  51. data [index].code != 0 || data [index].attribute != CharData.defaultAttr;
  52. }
  53. public func hasAnyContent () -> Bool {
  54. for i in 0..<data.count {
  55. if hasContent(index: i) {
  56. return true
  57. }
  58. }
  59. return false
  60. }
  61. public func insertCells (pos: Int, n: Int, rightMargin: Int, fillData: CharData)
  62. {
  63. let len = rightMargin + 1
  64. //let len = data.count
  65. let pos = pos % len
  66. if n < len - pos {
  67. for i in (0..<len-pos-n).reversed() {
  68. data [pos+n+i] = data [pos+i]
  69. }
  70. for i in 0..<n {
  71. data [pos+i] = fillData
  72. }
  73. } else {
  74. for i in pos..<len {
  75. data [i] = fillData
  76. }
  77. }
  78. }
  79. public func deleteCells (pos: Int, n: Int, rightMargin: Int, fillData: CharData)
  80. {
  81. // let len = data.count
  82. let len = rightMargin + 1
  83. let p = pos % len
  84. if n < len - p {
  85. for i in 0..<len-pos-n {
  86. data [pos+i] = self [pos+n+i]
  87. }
  88. for i in len-n..<len {
  89. data [i] = fillData
  90. }
  91. } else {
  92. for i in pos..<len {
  93. data [i] = fillData
  94. }
  95. }
  96. }
  97. public func replaceCells (start : Int, end : Int, fillData : CharData)
  98. {
  99. let length = data.count
  100. var idx = start
  101. while idx < end && idx < length {
  102. data [idx] = fillData
  103. idx += 1
  104. }
  105. }
  106. public func resize (cols : Int, fillData : CharData)
  107. {
  108. let len = data.count
  109. if len == cols {
  110. return
  111. }
  112. if cols > len {
  113. var newData = Array.init(repeating: fillData, count: cols)
  114. if len > 0 {
  115. for i in 0..<len {
  116. newData [i] = data [i]
  117. }
  118. }
  119. data = newData
  120. } else {
  121. if cols > 0 {
  122. data = Array.init (data [0..<cols])
  123. } else {
  124. data = [CharData]()
  125. }
  126. }
  127. }
  128. public func fill (with: CharData)
  129. {
  130. for i in 0..<data.count {
  131. data [i] = with
  132. }
  133. }
  134. public func fill (with: CharData, atCol: Int, len: Int)
  135. {
  136. for i in 0..<len {
  137. data [i+atCol] = with
  138. }
  139. }
  140. public func copyFrom (line: BufferLine)
  141. {
  142. if data.count != line.count {
  143. data = Array.init (repeating: CharData.Null, count: line.count)
  144. }
  145. for i in 0..<line.count {
  146. data [i] = line [i]
  147. }
  148. isWrapped = line.isWrapped
  149. }
  150. public func getTrimmedLength () -> Int
  151. {
  152. for i in (0..<data.count).reversed() {
  153. if data [i].code != 0 {
  154. var width = 0
  155. for _ in 0...i {
  156. width += Int (data [i].width)
  157. }
  158. return width
  159. }
  160. }
  161. return 0
  162. }
  163. public func copyFrom (_ src: BufferLine, srcCol: Int, dstCol: Int, len: Int)
  164. {
  165. data.replaceSubrange(dstCol..<(dstCol+len), with: src.data [srcCol..<(srcCol+len)])
  166. }
  167. public func translateToString (trimRight: Bool = false, startCol: Int = 0, endCol: Int = -1) -> String
  168. {
  169. var ec = endCol == -1 ? data.count : endCol
  170. if trimRight {
  171. ec = min (ec, getTrimmedLength())
  172. }
  173. var result = ""
  174. for i in startCol..<ec {
  175. result.append (data [i].getCharacter ())
  176. }
  177. return result
  178. }
  179. public var debugDescription: String {
  180. get {
  181. translateToString()
  182. }
  183. }
  184. }