mirror of
				https://github.com/minetest-mods/digilines.git
				synced 2025-10-31 06:35:22 +01:00 
			
		
		
		
	rework the whole line breaking algorithm and indicate its rules in the function
This commit is contained in:
		
							
								
								
									
										93
									
								
								lcd.lua
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								lcd.lua
									
									
									
									
									
								
							| @@ -30,33 +30,88 @@ local NUMBER_OF_LINES = 5 | |||||||
| local LINE_HEIGHT = 14 | local LINE_HEIGHT = 14 | ||||||
| local CHAR_WIDTH = 5 | local CHAR_WIDTH = 5 | ||||||
|  |  | ||||||
|  | local split = function(s, pat) | ||||||
|  | 	-- adapted from https://stackoverflow.com/a/1647577/4067384 | ||||||
|  | 	pat = pat or '%s+' | ||||||
|  | 	local st, g = 1, string.gmatch(s, "()("..pat..")") | ||||||
|  | 	local function getter(segs, seps, sep, cap1, ...) | ||||||
|  | 		st = sep and seps + #sep | ||||||
|  | 		return string.sub(s, segs, (seps or 0) - 1), cap1 or sep, ... | ||||||
|  | 	end | ||||||
|  | 	return function() if st then return getter(st, g()) end end | ||||||
|  | end | ||||||
|  |  | ||||||
| local create_lines = function(text) | local create_lines = function(text) | ||||||
|  | 	--[[ | ||||||
|  | 	  Typeset the lines according to these rules (in order of subjective significance): | ||||||
|  | 	  - words that fit on the screen but would let the current line overflow are placed on a new line instead | ||||||
|  | 	  - " | " always forces a linebreak | ||||||
|  | 	  - spaces are included, except when there is a linebreak anyway | ||||||
|  | 	  - words with more characters than fit on screen are just chopped up, filling the lines as full as possible | ||||||
|  | 	  - don't bother typesetting more lines than fit on screen | ||||||
|  | 	  - if we are on the last line that will fit on screen | ||||||
|  | 	]]-- | ||||||
| 	local line = "" | 	local line = "" | ||||||
| 	local line_num = 1 | 	local line_num = 1 | ||||||
| 	local tab = {} | 	local tab = {} | ||||||
| 	for word in string.gmatch(text, "%S*") do | 	local flush_line_and_check_for_return = function() | ||||||
| 		if (string.len(line) and string.len(line)+1) + string.len(word) <= LINE_LENGTH and word ~= "|" then | 		table.insert(tab, line) | ||||||
| 			if line ~= "" then | 		line_num = line_num+1 | ||||||
| 				line = line.." "..word | 		if line_num > NUMBER_OF_LINES then | ||||||
|  | 			return true | ||||||
|  | 		end | ||||||
|  | 		line = "" | ||||||
|  | 	end | ||||||
|  | 	for par in split(text, " | ") do | ||||||
|  | 		for word in split(par, "%s") do | ||||||
|  | 			if string.len(word) <= LINE_LENGTH and line_num < NUMBER_OF_LINES then | ||||||
|  | 				local line_len = string.len(line) | ||||||
|  | 				if line_len > 0 then | ||||||
|  | 					-- remember the space | ||||||
|  | 					line_len = line_len + 1 | ||||||
|  | 				end | ||||||
|  | 				if line_len + string.len(word) <= LINE_LENGTH then | ||||||
|  | 					if line_len > 0 then | ||||||
|  | 						line = line.." "..word | ||||||
|  | 					else | ||||||
|  | 						line = word | ||||||
|  | 					end | ||||||
|  | 				else | ||||||
|  | 					if word == " " then | ||||||
|  | 						-- don't add the space since we have a line break | ||||||
|  | 					else | ||||||
|  | 						if line_len > 0 then | ||||||
|  | 							-- ok, we need the new line | ||||||
|  | 							if flush_line_and_check_for_return() then return tab end | ||||||
|  | 						end | ||||||
|  | 						line = word | ||||||
|  | 					end | ||||||
|  | 				end | ||||||
| 			else | 			else | ||||||
| 				line = word | 				-- chop up word to make it fit | ||||||
| 			end | 				local remaining | ||||||
| 		else | 				while true do | ||||||
| 			table.insert(tab, line) | 					remaining = LINE_LENGTH - string.len(line) | ||||||
| 			if word == " " then | 					if remaining < LINE_LENGTH then | ||||||
| 				-- don't at the space since we have a line break | 						line = line .. " " | ||||||
| 			elseif word ~= "|" then | 						remaining = remaining - 1 | ||||||
| 				line = word | 					end | ||||||
| 			else | 					if remaining - string.len(word) < 0 then | ||||||
| 				line = "" | 						line = line .. string.sub(word, 1, math.min(remaining, string.len(word))) | ||||||
| 			end | 						word = string.sub(word, remaining+1, string.len(word)) | ||||||
| 			line_num = line_num+1 | 						if flush_line_and_check_for_return() then return tab end | ||||||
| 			if line_num > NUMBER_OF_LINES then | 					else | ||||||
| 				return tab | 						-- used up the word | ||||||
|  | 						line = line .. word | ||||||
|  | 						break | ||||||
|  | 					end | ||||||
|  | 				end | ||||||
| 			end | 			end | ||||||
| 		end | 		end | ||||||
|  | 		-- end of paragraph | ||||||
|  | 		if flush_line_and_check_for_return() then return tab end | ||||||
|  | 		line = "" | ||||||
| 	end | 	end | ||||||
| 	table.insert(tab, line) |  | ||||||
| 	return tab | 	return tab | ||||||
| end | end | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user