# calc_fns.ludic - min(a, b, ...), max(a, b, ...) and clamp(least, want, most) over lengths or plain # numbers, inside calc() or on their own. Comparing needs a length: a percentage there has no room yet. # the function a value starts with at `at` (calc, min, max or clamp), or "" function ca_fn_at(s: string, at: int) -> string { if ca_word(s, at, "calc(") { return "calc" } if ca_word(s, at, "min(") { return "min" } if ca_word(s, at, "max(") { return "max" } if ca_word(s, at, "clamp(") { return "clamp" } return "" } function ca_word(s: string, at: int, w: string) -> bool { return at + len(w) <= len(s) and sat(s, at, w) } function ca_fn(ui_st: mut UiState, f: string) -> CaVal { ui_st.ca_i = ui_st.ca_i + len(f) + 1 let depth = ui_st.ca_depth # min(calc(...)) nests: a kept list of arguments a depth @alloc_ok("once per depth of nesting, then kept") while len(ui_st.ca_args) <= depth { ui_kept(ui_st.ca_args, new []CaVal) } let args = ui_st.ca_args[depth] List.clear(args) ui_st.ca_depth = depth + 1 while ui_st.ca_bad == "" { ui_kept(args, ca_sum(ui_st)) ca_ws(ui_st) if ui_st.ca_i < len(ui_st.ca_s) and ui_st.ca_s[ui_st.ca_i] == 44 { ui_st.ca_i += 1 } else { break } } ui_st.ca_depth = depth if ui_st.ca_bad == "" and (ui_st.ca_i >= len(ui_st.ca_s) or ui_st.ca_s[ui_st.ca_i] != 41) { ui_st.ca_bad = "a closing )" } ui_st.ca_i += 1 if ui_st.ca_bad != "" { return ca_new(ui_st) } if f == "clamp" and len(args) != 3 { ui_st.ca_bad = "clamp(least, want, most)" return ca_new(ui_st) } for i in 0 .. len(args) { if args[i].pct != 0.0 { @alloc_ok("only when a template is wrong: a broken screen, never a working one") ui_st.ca_bad = `lengths in {f}(), not a percentage` return ca_new(ui_st) } } if f == "clamp" { return ca_pick(ui_st, ca_pick(ui_st, args[1], args[0], false), args[2], true) } var r = args[0] for i in 1 .. len(args) { r = ca_pick(ui_st, r, args[i], f == "min") } return r } # the smaller (or the larger) of two, a bare number beside a length being px function ca_pick(ui_st: mut UiState, a: CaVal, b: CaVal, smaller: bool) -> CaVal { if a.bare and b.bare { if (b.n < a.n) == smaller and b.n != a.n { return b } return a } let la = ca_len(ui_st, a) let lb = ca_len(ui_st, b) if (lb.px < la.px) == smaller and lb.px != la.px { return lb } return la }