-- text editor, particularly text drawing, horizontal wrap, vertical scrolling Text = {} -- draw a line starting from startpos to screen at y between State.left and State.right -- return y for the next line function Text.draw(State, line_index, y, startpos) --? print('text.draw', line_index, y) local line = State.lines[line_index] local line_cache = State.line_cache[line_index] line_cache.startpos = startpos -- wrap long lines Text.populate_screen_line_starting_pos(State, line_index) assert(#line_cache.screen_line_starting_pos >= 1, 'line cache missing screen line info') for i=1,#line_cache.screen_line_starting_pos do local pos = line_cache.screen_line_starting_pos[i] if pos < startpos then -- render nothing else local screen_line = Text.screen_line(line, line_cache, i) --? print('text.draw:', screen_line, 'at', line_index,pos, 'after', x,y) local frag_len = utf8.len(screen_line) -- render any highlights if State.selection1.line then local lo, hi = Text.clip_selection(State, line_index, pos, pos+frag_len) Text.draw_highlight(State, line, State.left,y, pos, lo,hi) end if line_index == State.cursor1.line then -- render search highlight or cursor if State.search_term then local data = State.lines[State.cursor1.line].data local cursor_offset = Text.offset(data, State.cursor1.pos) if data:sub(cursor_offset, cursor_offset+#State.search_term-1) == State.search_term then local save_selection = State.selection1 State.selection1 = {line=line_index, pos=State.cursor1.pos+utf8.len(State.search_term)} local lo, hi = Text.clip_selection(State, line_index, pos, pos+frag_len) Text.draw_highlight(State, line, State.left,y, pos, lo,hi) State.selection1 = save_selection end else if pos <= State.cursor1.pos and pos + frag_len > State.cursor1.pos then Text.draw_cursor(State, State.left+Text.x(State.font, screen_line, State.cursor1.pos-pos+1), y) elseif pos + frag_len == State.cursor1.pos then -- Show cursor at end of line. -- This place also catches end of wrapping screen lines. That doesn't seem worth distinguishing. -- It seems useful to see a cursor whether your eye is on the left or right margin. Text.draw_cursor(State, State.left+Text.x(State.font, screen_line, State.cursor1.pos-pos+1), y) end end end -- render screen line App.color(Text_color) App.screen.print(screen_line, State.left,y) y = y + State.line_height if y >= App.screen.height then break end end end return y end function Text.screen_line(line, line_cache, i) local pos = line_cache.screen_line_starting_pos[i] local offset = Text.offset(line.data, pos) if i >= #line_cache.screen_line_starting_pos then return line.data:sub(offset) end local endpos = line_cache.screen_line_starting_pos[i+1]-1 local end_offset = Text.offset(line.data, endpos) return line.data:sub(offset, end_offset) end function Text.draw_cursor(State, x, y) -- blink every 0.5s if math.floor(Cursor_time*2)%2 == 0 then App.color(Cursor_color) love.graphics.rectangle('fill', x,y, 3,State.line_height) end State.cursor_x = x State.cursor_y = y+State.line_height end function Text.populate_screen_line_starting_pos(State, line_index) local line = State.lines[line_index] local line_cache = State.line_cache[line_index] if line_cache.screen_line_starting_pos then return end line_cache.screen_line_starting_pos = {1} local x = 0 local pos = 1 -- try to wrap at word boundaries for frag in line.data:gmatch('%S*%s*') do local frag_width = State.font:getWidth(frag) --? print('-- frag:', frag, pos, x, frag_width, State.width) while x + frag_width > State.width do --? print('frag:', frag, pos, x, frag_width, State.width) if x < 0.8 * State.width then -- long word; chop it at some letter -- We're not going to reimplement TeX here. local bpos = Text.nearest_pos_less_than(State.font, frag, State.width - x) if x == 0 and bpos == 0 then assert(false, ("Infinite loop while line-wrapping. Editor is %dpx wide; window is %dpx wide"):format(State.width, App.screen.width)) end pos = pos + bpos local boffset = Text.offset(frag, bpos+1) -- byte _after_ bpos frag = string.sub(frag, boffset) --? if bpos > 0 then --? print('after chop:', frag) --? end frag_width = State.font:getWidth(frag) end --? print('screen line:', pos) table.insert(line_cache.screen_line_starting_pos, pos) x = 0 -- new screen line end x = x + frag_width pos = pos + utf8.len(fra
# dwm - dynamic window manager
# © 2006-2007 Anselm R. Garbe, Sander van Dijk
include config.mk
SRC = dwm.c
OBJ = ${SRC:.c=.o}
all: options dwm
options:
@echo dwm build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
${OBJ}: config.h config.mk
config.h:
@echo creating $@ from config.def.h
@cp config.def.h $@
dwm: ${OBJ}
@echo CC -o $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
clean:
@echo cleaning
@rm -f dwm ${OBJ} dwm-${VERSION}.tar.gz
dist: clean
@echo creating dist tarball
@mkdir -p dwm-${VERSION}
@cp -R LICENSE Makefile README config.def.h config.mk \
dwm.1 ${SRC} dwm-${VERSION}
@tar -cf dwm-${VERSION}.tar dwm-${VERSION}
@gzip dwm-${VERSION}.tar
@rm -rf dwm-${VERSION}
install: all
@echo installing executable file to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f dwm ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/dwm
@echo installing manual page to ${DESTDIR}${MANPREFIX}/man1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1
@sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1
uninstall:
@echo removing executable file from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/dwm
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/dwm.1
.PHONY: all options clean dist install uninstall