func update_candidates(serial int, input string, providersp unsafe.Pointer, info map[string]interface{}) { texts := make(map[string]bool) providers := make(map[string][]string) descriptions := make(map[string][]string) distances := make(map[string]int) var lock sync.Mutex // from GlobalVocabulary l := GlobalVocabulary.Len() var word *Word for i := 0; i < l; i++ { word = GlobalVocabulary.GetByIndex(i) if match, distance := fuzzyMatch(word.Text, input); match { texts[word.Text] = true distances[word.Text] = distance providers[word.Text] = []string{} } } // get buffer content buffer := (*C.GtkTextBuffer)(info["buffer"].(unsafe.Pointer)) var start_iter, end_iter C.GtkTextIter C.gtk_text_buffer_get_start_iter(buffer, &start_iter) C.gtk_text_buffer_get_end_iter(buffer, &end_iter) cContent := C.gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, C.gtk_false()) content := C.GoBytes(unsafe.Pointer(cContent), C.int(C.strlen((*C.char)(cContent)))) result := sort(input, texts, distances, providers, descriptions) // extra providers for source, provider := range (*Providers)(providersp).Providers { go func() { lock.Lock() for _, pair := range provider(input, content, info) { text := pair[0] if input != "" { if match, _ := fuzzyMatch(text, input); !match { continue } } GlobalVocabulary.Add(text) texts[text] = true providers[text] = append(providers[text], source) descriptions[text] = append(descriptions[text], "<"+source+"> "+pair[1]) distances[text] = 0 } result := sort(input, texts, distances, providers, descriptions) lock.Unlock() C.emit() results <- Result{serial, result} }() } updateStore(result) }
func (t *textbox) Text() string { var start, end C.GtkTextIter buf := C.gtk_text_view_get_buffer(t.textview) C.gtk_text_buffer_get_bounds(buf, &start, &end) // include hidden chars even though there can't be one since Textbox is explicitly unformatted just to be safe // don't worry about embedded pixbufs or widgets; those aren't allowed either ctext := C.gtk_text_buffer_get_text(buf, &start, &end, C.TRUE) // not explicitly documented: have to manually free this (thanks ste in irc.gimp.net/#gtk+) defer C.g_free(C.gpointer(unsafe.Pointer(ctext))) return fromgstr(ctext) }
func collect_words(bufferp unsafe.Pointer, isEditMode bool, rep unsafe.Pointer) { var start_iter, end_iter C.GtkTextIter buf := (*C.GtkTextBuffer)(bufferp) C.gtk_text_buffer_get_start_iter(buf, &start_iter) C.gtk_text_buffer_get_end_iter(buf, &end_iter) text := []byte(C.GoString((*C.char)(C.gtk_text_buffer_get_text(buf, &start_iter, &end_iter, C.gtk_false())))) C.gtk_text_buffer_get_iter_at_mark(buf, &start_iter, C.gtk_text_buffer_get_insert(buf)) cursor_char_offset := int(C.gtk_text_iter_get_offset(&start_iter)) go func() { byte_offset := 0 char_offset := 0 re := (*regexp.Regexp)(rep) decode_byte_offset := 0 var word_start_char_offset, word_end_char_offset int var size int for { // find next word loc := re.FindIndex(text[byte_offset:]) if loc == nil { return } // convert byte offset to char offset byte_offset += loc[0] for decode_byte_offset < byte_offset { _, size = utf8.DecodeRune(text[decode_byte_offset:]) decode_byte_offset += size char_offset += 1 } word_start_char_offset = char_offset byte_offset += loc[1] - loc[0] for decode_byte_offset < byte_offset { _, size = utf8.DecodeRune(text[decode_byte_offset:]) decode_byte_offset += size char_offset += 1 } word_end_char_offset = char_offset // skip current word in edit mode if isEditMode { if cursor_char_offset >= word_start_char_offset && cursor_char_offset <= word_end_char_offset { continue } } // add to global vocabulary GlobalVocabulary.Add(string(text[byte_offset-(loc[1]-loc[0]) : byte_offset])) } }() }