@@ -984,7 +984,7 @@ open class Terminal {
984984 xtermTitleSetHex = false
985985 xtermTitleQueryHex = false
986986
987- hyperLinkTracking = nil
987+ activeHyperlink = nil
988988 cursorBlink = false
989989 hostCurrentDirectory = nil
990990 lineFeedMode = options. convertEol
@@ -1309,7 +1309,11 @@ open class Terminal {
13091309 }
13101310 if allAscii {
13111311 updateRange ( borrowing: buffer, buffer. y)
1312- let consumed = buffer. insertAsciiRun ( data, attribute: curAttr)
1312+ let consumed = buffer. insertAsciiRun (
1313+ data,
1314+ attribute: curAttr,
1315+ resolvePayload: { self . resolveActiveHyperlink ( ) }
1316+ )
13131317 if consumed == data. count {
13141318 updateRange ( borrowing: buffer, buffer. y)
13151319 return
@@ -1345,7 +1349,7 @@ open class Terminal {
13451349 // Every single mapping in the charset only takes one slot
13461350 chWidth = 1
13471351 let charData = makeCharData ( attribute: curAttr, char: ch, size: Int8 ( chWidth) )
1348- buffer . insertCharacter ( charData)
1352+ insertCharacter ( charData)
13491353 continue
13501354 }
13511355 }
@@ -1354,7 +1358,7 @@ open class Terminal {
13541358 chWidth = UnicodeUtil . columnWidth ( rune: rune)
13551359 if chWidth > 0 {
13561360 let charData = makeCharData ( attribute: curAttr, scalar: rune, size: Int8 ( chWidth) )
1357- buffer . insertCharacter ( charData)
1361+ insertCharacter ( charData)
13581362 }
13591363 continue
13601364 } else if readingBuffer. bytesLeft ( ) >= ( n- 1 ) {
@@ -1383,7 +1387,7 @@ open class Terminal {
13831387 chWidth = UnicodeUtil . columnWidth ( rune: rune)
13841388 if chWidth > 0 {
13851389 let charData = makeCharData ( attribute: curAttr, scalar: rune, size: Int8 ( chWidth) )
1386- buffer . insertCharacter ( charData)
1390+ insertCharacter ( charData)
13871391 }
13881392 continue
13891393 }
@@ -1498,6 +1502,7 @@ open class Terminal {
14981502 let nextX = lastx + 1
14991503 var empty = makeCharData ( attribute: cd. attribute, code: 0 , size: 0 )
15001504 empty. setSemanticContent ( cd. semanticContent)
1505+ empty. setPayload ( atom: cd. payload)
15011506 existingLine [ nextX] = empty
15021507 buffer. x += 1
15031508 } else {
@@ -1513,6 +1518,7 @@ open class Terminal {
15131518 updateCharData ( & cd, char: newCh, size: 2 )
15141519 var empty = makeCharData ( attribute: cd. attribute, code: 0 , size: 0 )
15151520 empty. setSemanticContent ( cd. semanticContent)
1521+ empty. setPayload ( atom: cd. payload)
15161522 existingLine [ lastx + 1 ] = empty
15171523 buffer. x += 1
15181524 } else {
@@ -1537,7 +1543,7 @@ open class Terminal {
15371543 // emitChar (ch)
15381544 //}
15391545 let charData = makeCharData ( attribute: curAttr, char: ch, size: Int8 ( chWidth) )
1540- buffer . insertCharacter ( charData)
1546+ insertCharacter ( charData)
15411547 }
15421548 updateRange ( borrowing: buffer, buffer. y)
15431549 readingBuffer. done ( )
@@ -1612,9 +1618,10 @@ open class Terminal {
16121618 // Inserts the specified character with the computed width into the next cell, following
16131619 // the rules for wrapping around, scrolling and overflow expected in the terminal.
16141620 func insertCharacter ( _ charData: CharData ) {
1615- // TODO, make this a direct call. no need to pproxy here
16161621 buffer. insertCharacter (
1617- charData)
1622+ charData,
1623+ resolvePayload: { self . resolveActiveHyperlink ( ) }
1624+ )
16181625 }
16191626
16201627// func insertCharacter2(_ charData: CharData) {
@@ -2601,9 +2608,35 @@ open class Terminal {
26012608 }
26022609 }
26032610
2604- var hyperLinkTracking : ( start: Position , payload: String ) ? = nil
2611+ private enum ActiveHyperlink {
2612+ case pending( String )
2613+ case resolved( TinyAtom )
2614+ case unavailable
2615+ }
2616+
2617+ private var activeHyperlink : ActiveHyperlink ? = nil
26052618 private var payloadCodes = Set < UInt16 > ( )
26062619
2620+ private func resolveActiveHyperlink( ) -> TinyAtom ? {
2621+ guard let activeHyperlink else {
2622+ return nil
2623+ }
2624+
2625+ switch activeHyperlink {
2626+ case . pending( let payload) :
2627+ guard let atom = makePayload ( value: payload) else {
2628+ self . activeHyperlink = . unavailable
2629+ return nil
2630+ }
2631+ self . activeHyperlink = . resolved( atom)
2632+ return atom
2633+ case . resolved( let atom) :
2634+ return atom
2635+ case . unavailable:
2636+ return nil
2637+ }
2638+ }
2639+
26072640 /// Creates a payload atom whose lifetime is managed by this terminal.
26082641 ///
26092642 /// ``garbageCollectPayload()`` releases the atom after it is no longer present in
@@ -2619,35 +2652,11 @@ open class Terminal {
26192652
26202653 func oscHyperlink ( _ data: ArraySlice < UInt8 > )
26212654 {
2622- let buffer = self . buffer
26232655 if data. count == 1 && data [ data. startIndex] == UInt8 ( ascii: " ; " ) {
2624- // We only had the terminator, so we can close ";"
2625- if let hlt = hyperLinkTracking {
2626- let str = hlt. payload
2627- if let urlToken = makePayload ( value: str) {
2628- //print ("Setting the text from \(hlt.start) to \(buffer.x) on line \(buffer.y+buffer.yBase) to \(str)")
2629-
2630- // Between the time the flag was set, and now `y` might have changed negatively,
2631- // in that case, we do not flag any sequence as a hyperlink
2632- if hlt. start. row <= buffer. y+ buffer. yBase {
2633- for y in hlt. start. row... ( buffer. y+ buffer. yBase) {
2634- let line = buffer. lines [ y]
2635- let startCol = y == hlt. start. row ? min ( hlt. start. col, cols- 1 ) : 0
2636- let endCol = y == buffer. y ? min ( buffer. x, cols- 1 ) : ( marginMode ? buffer. marginRight : cols- 1 )
2637- if endCol > startCol {
2638- for x in startCol... endCol {
2639- var cd = line [ x]
2640- cd. setPayload ( atom: urlToken)
2641- line [ x] = cd
2642- }
2643- }
2644- }
2645- }
2646- }
2647- }
2648- hyperLinkTracking = nil
2656+ activeHyperlink = nil
26492657 } else {
2650- hyperLinkTracking = ( start: Position ( col: buffer. x, row: buffer. y+ buffer. yBase) , payload: String ( bytes: data, encoding: . ascii) ?? " " )
2658+ let payload = String ( bytes: data, encoding: . ascii) ?? " "
2659+ activeHyperlink = . pending( payload)
26512660 }
26522661 }
26532662
@@ -4592,7 +4601,7 @@ open class Terminal {
45924601 charset = nil
45934602 setgLevel ( 0 )
45944603 conformance = . vt500
4595- hyperLinkTracking = nil
4604+ activeHyperlink = nil
45964605 lineFeedMode = options. convertEol
45974606 resetAllColors ( )
45984607 tdel? . showCursor ( source: self )
@@ -6281,6 +6290,9 @@ open class Terminal {
62816290
62826291 // check all atoms used in both buffers
62836292 var used = Set < UInt16 > ( )
6293+ if let activeHyperlink, case . resolved( let atom) = activeHyperlink {
6294+ used. insert ( atom. code)
6295+ }
62846296 for buffer in [ normalBuffer, altBuffer] {
62856297 // TODO use a better system than this ugly nest
62866298 for line in buffer. lines. getArray ( ) {
0 commit comments