NEDIT_require_macro_file("extensions.nm") # $backlights[win]["groupName"]["charRanges"] = "0-8,11-31,127" # $backlights[win]["groupName"]["colorValue"] = "#c8e8d8" $backlights[""] = "" # ============================================================================== # backlight_set_from_range(rangestring [, addchars [, remchars]]): creates a # string of ascii characters for the specified range specification. Note # that character zero is ignored. If addchars is given, this provides # extra characters to add to the set; similarly, characters from remchars # are removed. # ============================================================================== define backlight_set_from_range { set = $empty_array addchars = "" remchars = "" rs = $1 if ($n_args > 1) addchars = $2 if ($n_args > 2) remchars = $3 while (search_string(rs, "^\\d+(?:-\\d+)?", 0, "regex") != -1) { r = replace_in_string(rs, "^(\\d+(-\\d+)?).*", "\\1", "regex") rs = replace_in_string(rs, "^(\\d+(-\\d+)?),?(.*)", "\\3", "regex") #DEBUG("\tbacklight_set_from_range("$1"): range='"r"' rest='"rs"' ") if (search_string(r, "^\\d+-\\d+", 0, "regex") != -1) { lo = replace_in_string(r, "^(\\d+).*", "\\1", "regex") hi = replace_in_string(r, "^\\d+-(\\d+).*", "\\1", "regex") } else { lo = r hi = r } #DEBUG(" lo="lo" hi="hi"\n") for (i = lo; i <= hi; i++) { if (i == 0) continue ch = tochar(i) if (search_string(remchars, ch, 0) < 0) # only add if not to be removed set[ch] = 1 } } # add characters in addchars hi = length(addchars) for (i = 0; i < hi; i++) { ch = substring(addchars, i, i + 1) if (search_string(remchars, ch, 0) < 0) # only add if not to be removed { #DEBUG("\tbacklight_set_from_range(): adding char '"ch"'\n") set[ch] = 1 } } res = "" for (s in set) res = res s #DEBUG("\tbacklight_set_from_range('"$1"','"addchars"','"remchars"'): set=["res"]\n") return res } # ============================================================================== # backlight_range_from_set(setstring): creates a range specification # corresponding to the string of ascii characters. Note that character # zero is ignored. # ============================================================================== define backlight_range_from_set { set = $empty_array for (i = 0; i < length($1); i++) set[substring($1, i, i + 1)] = 1 #DEBUG("\tbacklight_range_from_set('"$1"')\n") lo = -1 hi = -1 res = "" sep = "" for (s in set) { i = toascii(s) if (lo < 0) { lo = i hi = i } else if (hi + 1 == i) hi = i else # gap between hi and i { if (lo == hi) res = res sep lo else res = res sep lo "-" hi sep = "," lo = i hi = i } } # catch the last range if (lo >= 0) { if (lo == hi) res = res sep lo else res = res sep lo "-" hi } #DEBUG("\tbacklight_range_from_set('"$1"'): '"res"'\n") return res } # ============================================================================== # backlight_assign(resourcestr): creates an array suitable for assignment to # $backlights from the given resource string. This is of the form # ["group "n]["charRanges"] = char-range-string # ["group "n]["colorValue"] = color-value # where n is a right justified number. # ============================================================================== define backlight_assign { res = $empty_array groups = split($1, ";") n = groups[] - 1 for (i = 0; i in groups; i++) { parts = split(groups[i], ":") elem["charRanges"] = parts[0] elem["colorValue"] = parts[1] res["group" rjust(i, n)] = elem } return res } # ============================================================================== # backlight_make_string(array): creates a resource string from a suitable array. # ============================================================================== define backlight_make_string { s = "" for (i in $1) { r = $1[i]["charRanges"] c = $1[i]["colorValue"] if (length(r) && length(c)) s = s r ":" c ";" } if (s == "") s = ";" return substring(s, 0, -1) } # ============================================================================== # backlight_use_stored_group_names(olda, newa): checks newa's group names # against the ones stored in olda by matching charRanges entries: it # renames the newa's group names then returns it. # ============================================================================== define backlight_use_stored_group_names { olda = $1 newa = $2 oldl = $empty_array newl = oldl i = 0 for (og in olda) { for (ng in newa) { if (newa[ng]["charRanges"] == olda[og]["charRanges"]) if (ng != og && !(og in newa)) { newl[i] = ng oldl[i] = og i++ } } } for (i in newl) { ng = newl[i] og = oldl[i] newa[og] = newa[ng] delete newa[ng] } return newa } # ============================================================================== # backlight_display_build_lines(array): generates a string holding lines # suitable for a list_dialog() from the backlight array passed. # ============================================================================== define backlight_display_build_lines { array = $1 res = "" glen = 0 rlen = 0 clen = 0 # measure max lengths for (g in array) { glen = max(glen, length(g)) rlen = max(rlen, length(array[g]["charRanges"])) clen = max(clen, length(array[g]["colorValue"])) } # generate a space padding string len = max(glen, rlen, clen) sp = " " while (length(sp) < len) sp = sp sp # now generate the strings for (g in array) { gs = substring(g sp, 0, glen) rs = substring(array[g]["charRanges"] sp, 0, rlen) cs = substring(array[g]["colorValue"] sp, 0, clen) res = res gs " | " rs " | " cs "\n" } return res } # ============================================================================== # backlight_display_groups(title, array, button...): presents a list of groups # held in array, adding buttons as taken from the argument list. It # returns an array holding keys "button" (number of button pressed, if # any), "buttonstr" (the button name or "Cancel"), "group", "charRanges" # and "colorValue" holding parts of the selected line. # ============================================================================== define backlight_display_groups { title = $1 array = $2 gline = backlight_display_build_lines(array) res["button"] = 0 if ($n_args <= 2) s = list_dialog(title, gline, "Cancel") else if ($n_args == 3) s = list_dialog(title, gline, $3, "Cancel") else if ($n_args == 4) s = list_dialog(title, gline, $3, $4, "Cancel") else if ($n_args == 5) s = list_dialog(title, gline, $3, $4, $5, "Cancel") else if ($n_args == 6) s = list_dialog(title, gline, $3, $4, $5, $6, "Cancel") else if ($n_args == 7) s = list_dialog(title, gline, $3, $4, $5, $6, $7, "Cancel") else if ($n_args == 8) s = list_dialog(title, gline, $3, $4, $5, $6, $7, $8, "Cancel") else if ($n_args == 9) s = list_dialog(title, gline, $3, $4, $5, $6, $7, $8, $9, "Cancel") else return res button = $list_dialog_button cancel = min(8, $n_args - 1) if (button == cancel) { res["button"] = 0 res["buttonstr"] = "Cancel" } else { res["button"] = button res["buttonstr"] = $args[button + 2] } if (s != "") { parts = split(s, "\\s*\\|\\s*", "regex") res["group"] = parts[0] res["charRanges"] = parts[1] res["colorValue"] = parts[2] #DEBUG("backlight_display_groups(): '"s"'->") #for (i in res) DEBUG(" "i "='"res[i]"'") #DEBUG("\n") } return res } # ============================================================================== # backlight_get_backlights(): assembles the backlight groups into the array # $backlights. # ============================================================================== define backlight_get_backlights { # set_backlight_string() win = $file_path $file_name if (win in $backlights) { group = $backlights[win] current = backlight_assign($backlight_string) $backlights[win] = backlight_use_stored_group_names(group, current) } else $backlights[win] = backlight_assign($backlight_string) } # ============================================================================== # backlight_display_backlights(): displays the current window backlights. # ============================================================================== define backlight_display_backlights { # set_backlight_string() backlight = backlight_assign($backlight_string) backlight_display_groups("Backlighting for " $file_name, backlight) } # ============================================================================== # backlight_modify_range(oldr): walks the user through a number of dialogs, # modifying the range in different ways. Returns a new range, which may be # the same as the old range. # ============================================================================== define backlight_modify_range { keep_r = $1 set = backlight_set_from_range($1) #DEBUG("DEBUG range->set - #chars in range "$1": "length(set)"\n") r = keep_r ok = 1 done = 0 while (ok) { #DEBUG("DEBUG range is "r"\n") r = backlight_range_from_set(set) #DEBUG("DEBUG set->range - #chars in range "r": "length(set)"\n") ret = dialog("Current range is " r, \ "Done", \ "Enter new numeric\nrange", \ "Add text\ncharacters", \ "Remove text\ncharacters", \ "Add character\ncode(s)", \ "Remove character\ncode(s)", \ "Revert") ok = (1 < ret && ret < 7) done = ret == 1 if (done) return r if (ret == 2) # Enter new numeric range { str = string_dialog("Old range is '" r "'\nEnter new range:") if (str == "") { if (dialog("New range is empty\nKeep old range?", "Yes", "No") != 1) r = str } else { str = replace_in_string(str, "\\s+", "", "regex", "copy") rangesRE = "^\\d+(?:-\\d+)?(?:,\\d+(?:-\\d+)?)*$" if (search_string(str, rangesRE, 0, "regex") == 0) { set = backlight_set_from_range(str) } else { dialog("New range specification '"str"' is faulty", "Cancel") } } } else if (ret == 3) # Add text characters { str = string_dialog("Enter characters to add to set", "OK", "Cancel") if (str != "" && $string_dialog_button == 1) set = backlight_set_from_range(r, str) } else if (ret == 4) # Remove text characters { str = string_dialog("Enter characters to remove from set", "OK", "Cancel") if (str != "" && $string_dialog_button == 1) set = backlight_set_from_range(r, "", str) } else if (ret == 5) # Add character code(s) { dialog("Not implemented") } else if (ret == 6) # Remove character code(s) { dialog("Not implemented") } } return keep_r } # ============================================================================== # backlight_manip_backlights(): displays the array $backlights, assembling it # if necessary. # ============================================================================== define backlight_manip_backlights { backlight_get_backlights() groups = $backlights[$file_path $file_name] old = groups r["button"] = -1 changed = "" msg = "" while (r["button"]) { if (changed == "") r = backlight_display_groups(msg \ changed "Backlighting for " $file_name, \ groups, \ "Rename Group", \ "New Group", \ "Delete Group", \ "Modify Range", \ "Modify Color") else r = backlight_display_groups(msg \ changed "Backlighting for " $file_name, \ groups, \ "Rename Group", \ "New Group", \ "Delete Group", \ "Modify Range", \ "Modify Color", \ "Apply", \ "Revert") if (r["buttonstr"] == "Rename Group") { if (!("group" in r)) { msg = "Error: you need to select a group for "r["buttonstr"]"\n\n" continue } s = string_dialog("Rename group '" r["group"] "' to:") s = replace_in_string(s, "^\\s*", "", "regex") s = replace_in_string(s, "\\s*$", "", "regex") if (s == "" || search_string(s, "|", 0) != -1) { dialog("New group name " s " for group '" r["group"] "' " \ "invalid:\nmust not contain bars '|' and must not be empty") } else if (s in groups) { dialog("New group name " s " for group '" r["group"] "' " \ "invalid:\nthere is already a group with that name") } else { changed = "[**CHANGED**] " groups[s] = groups[r["group"]] delete groups[r["group"]] } } else if (r["buttonstr"] == "New Group") { s = string_dialog("Add new group:") s = replace_in_string(s, "^\\s*", "", "regex") s = replace_in_string(s, "\\s*$", "", "regex") if (s == "" && search_string(s, "|", 0) != -1) { dialog("New group name " s " for group '" r["group"] "' " \ "invalid:\nmust not contain bars '|' and must not be empty") } else if (s in groups) { dialog("New group name " s " for group '" r["group"] "' " \ "invalid:\nthere is already a group with that name") } else { changed = "[**CHANGED**] " newa["charRanges"] = "" newa["colorValue"] = "" groups[s] = newa } } else if (r["buttonstr"] == "Delete Group") { if (!("group" in r)) { msg = "Error: you need to select a group for "r["buttonstr"]"\n\n" continue } b = dialog("Deleting group '"r["group"]"'\nAre you sure?", "Yes", "No") if (b == 1) { delete groups[r["group"]] changed = "[**CHANGED**] " } } else if (r["buttonstr"] == "Modify Range") { if (!("group" in r)) { msg = "Error: you need to select a group for "r["buttonstr"]"\n\n" continue } range = backlight_modify_range(r["charRanges"]) if (range != r["charRanges"]) { groups[r["group"]]["charRanges"] = range changed = "[**CHANGED**] " } } else if (r["buttonstr"] == "Modify Color") { if (!("group" in r)) { msg = "Error: you need to select a group for "r["buttonstr"]"\n\n" continue } warn = "*** COLOR NAMES ARE NOT CHECKED ***\n" s = string_dialog(warn "New color for group '"r["group"]"':") s = replace_in_string(s, "^\\s*", "", "regex") s = replace_in_string(s, "\\s*$", "", "regex") groups[r["group"]]["colorValue"] = s changed = "[**CHANGED**] " } else if (r["buttonstr"] == "Apply") { old = groups s = backlight_make_string(groups) #dialog("Backlight string:\nold = "$backlight_string"\nnew = "s) set_backlight_string("") set_backlight_string(s) $backlights[$file_path $file_name] = groups changed = "" } else if (r["buttonstr"] == "Revert") { groups = old s = backlight_make_string(groups) #dialog("Backlight string:\nold = "$backlight_string"\nnew = "s) set_backlight_string("") set_backlight_string(s) $backlights[$file_path $file_name] = groups changed = "" } } } # ============================================================================== # backlight_color_addsub(value, delta, sign): adds or subtracts (according to # sign) value and delta on a byte by byte basis, making sure that the # value of the result's bytes are always in the range 0 to xFF. value and # delta must be integers (or decimal values). # ============================================================================== define backlight_color_addsub { value = $1 delta = $2 sign = $3 mask = 255 divide = 1 result = 0 res = 0 # DEBUG("backlight_color_addsub(value=#"int_to_hex(value,6) \ # ", delta=#"int_to_hex(delta,6)", sign='"sign"')\n") while (value != 0 || delta != 0) { # DEBUG("value=#"int_to_hex(value,6)" delta=#"int_to_hex(delta,6)"\n") val = (value / divide) & 255 dlt = (delta / divide) & 255 # DEBUG(" mask=#"int_to_hex(mask,6)"\n") # DEBUG(" val=#"int_to_hex(val,2)" "sign" dlt=#"int_to_hex(dlt,2)" = ") value &= compl(mask) # ie ~mask delta &= compl(mask) # ie ~mask res = val + (1 - 2 * (sign == "-")) * dlt res = max(0, min(res, 255)) # DEBUG(" res=#"int_to_hex(res,2)"\n") # DEBUG("result=#"int_to_hex(result,6)"\n") result += res * divide divide *= 256 mask *= 256 } return result } # ============================================================================== # backlight_assign_standard_groups([bg_color [, refbl]]): sets up a backlighting # string using the bg_color (if passed), which must be of the form # '#rrggbb' in hexadecimal, and refbl, a backlighting string which can # contain color "values" of the form '[-+]#rrggbb'. These values, if # present, are added or subtracted from the bg_color to determine a new # color, which will replace the fake color in the string. The function # returns the new backlighting string. The default value for bg_color is # the current one (if get_colors() works), and that of refbl is # "0-8,10-31,127:red;9:-#070707;32-126,160-255:+#131313;128-159:orange". # ============================================================================== define backlight_assign_standard_groups { # DEBUG("backlight_assign_standard_groups:\n") if ($n_args > 0) bg_color = $1 else bg_color = get_colors()["rgb_text_bg"] bg = hex_to_int(replace_in_string(bg_color, "#", "", "copy")) # DEBUG("bg_color='"bg_color"' -> bg="bg" ('#"int_to_hex(bg,6)"')\n") refbl = "0-8,10-31,127:red;9:-#070707;32-126,160-255:+#131313;128-159:orange" if ($n_args > 1) refbl = $2 bla = backlight_assign(refbl) for (i in bla) { col = bla[i]["colorValue"] sign = substring(col, 0, 1) if (sign == "+" || sign == "-") { if (substring(col, 1, 2) == "#") d = hex_to_int(substring(col, 2)) else d = substring(col, 1) v = backlight_color_addsub(bg, d, sign) bla[i]["colorValue"] = "#" int_to_hex(v, 6) } } return backlight_make_string(bla) }