para.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package mappers
  2. import (
  3. "github.com/kpmy/odf/mappers/attr"
  4. "github.com/kpmy/odf/model"
  5. "github.com/kpmy/odf/xmlns/text"
  6. "github.com/kpmy/ypk/assert"
  7. )
  8. //ParaMapper writes and controls text content in document model
  9. type ParaMapper struct {
  10. fm *Formatter
  11. rider model.Writer
  12. }
  13. func (p *ParaMapper) makePara() {
  14. if pos := p.rider.Pos(); pos.Name() == text.P {
  15. p.rider.Pos(p.fm.root)
  16. }
  17. p.rider.WritePos(New(text.P))
  18. p.fm.attr.Flush()
  19. p.fm.attr.Fit(text.P, func(a attr.Attributes) {
  20. p.rider.Attr(text.StyleName, a.Name())
  21. })
  22. }
  23. //ConnectTo Formatter that holds document model
  24. func (p *ParaMapper) ConnectTo(fm *Formatter) {
  25. p.fm = fm
  26. p.rider = fm.m.NewWriter()
  27. p.rider.Pos(fm.root)
  28. }
  29. //WritePara writes text in new paragraph with the most latest text and paragraph attributes set to connected Formatter
  30. func (p *ParaMapper) WritePara(s string) {
  31. if pos := p.rider.Pos(); pos.Name() == text.P {
  32. p.rider.Pos(pos.Parent())
  33. }
  34. p.rider.WritePos(New(text.P))
  35. p.fm.attr.Flush()
  36. p.fm.attr.Fit(text.P, func(a attr.Attributes) {
  37. p.rider.Attr(text.StyleName, a.Name())
  38. })
  39. p.WriteString(s)
  40. }
  41. //WriteString writes a text within existing paragraph or creates new paragraph if symbol \r met
  42. func (p *ParaMapper) WriteString(_s string) {
  43. assert.For(p.fm.ready, 20)
  44. buf := make([]rune, 0)
  45. count := 0
  46. flush := func(space bool) {
  47. p.rider.Write(model.Text(string(buf)))
  48. buf = make([]rune, 0)
  49. if space && count > 1 {
  50. w := p.fm.m.NewWriter(p.rider)
  51. w.WritePos(New(text.S))
  52. w.Attr(text.C, count)
  53. }
  54. }
  55. grow := func() {
  56. if count > 1 {
  57. flush(true)
  58. } else if count == 1 {
  59. buf = append(buf, ' ')
  60. }
  61. if len(buf) > 0 {
  62. flush(false)
  63. }
  64. count = 0
  65. }
  66. if p.rider.Pos().Name() != text.P {
  67. p.WritePara(_s)
  68. } else {
  69. p.fm.attr.Flush()
  70. p.fm.attr.Fit(text.Span, func(a attr.Attributes) {
  71. p.rider.WritePos(New(text.Span))
  72. p.rider.Attr(text.StyleName, a.Name())
  73. })
  74. s := []rune(_s)
  75. br := false
  76. for pos := 0; pos < len(s) && s[pos] != 0; {
  77. switch s[pos] {
  78. case ' ':
  79. count++
  80. case '\n':
  81. grow()
  82. p.rider.Write(New(text.LineBreak))
  83. case '\r':
  84. grow()
  85. p.fm.attr.Fit(text.Span, func(a attr.Attributes) {
  86. p.rider.Pos(p.rider.Pos().Parent())
  87. })
  88. //skip cr+lf
  89. if pos+1 < len(s) && s[pos+1] == '\n' {
  90. pos = pos + 1
  91. }
  92. for pos = pos + 1; pos < len(s); pos++ {
  93. buf = append(buf, s[pos])
  94. }
  95. p.WritePara(string(buf))
  96. pos--
  97. br = true
  98. case '\t':
  99. grow()
  100. p.rider.Write(New(text.Tab))
  101. default:
  102. if count > 1 {
  103. flush(true)
  104. } else if count == 1 {
  105. buf = append(buf, ' ')
  106. }
  107. count = 0
  108. buf = append(buf, s[pos])
  109. }
  110. pos++
  111. }
  112. if !br {
  113. grow()
  114. p.fm.attr.Fit(text.Span, func(a attr.Attributes) {
  115. p.rider.Pos(p.rider.Pos().Parent())
  116. })
  117. }
  118. }
  119. }