FUNCTION fill_text (string_in IN VARCHAR2, linesize_in IN NUMBER) RETURN VARCHAR2 IS /* || Parameters: || string_in - the string to justify. || linesize_in - the length of the line to which string is justified. */ -- The length of the string. len_string NUMBER := LENGTH (string_in); -- I will give a name to the blank to make the code more readable. a_blank CONSTANT VARCHAR2(1) := ' '; -- The starting location for INSTR checks. start_loc NUMBER; -- A Boolean variable to control execution of the inner WHILE loop. keep_adding_blanks BOOLEAN; -- The location in the string of the next blank. nextblank_loc NUMBER; /* || The return value for the function is initially set to the incoming || string. I also LTRIM and RTRIM it to get rid of end spaces. || I am going to assume a max line size of 500. You could raise this || limit to 32K, but you will use more memory to do so. */ return_value VARCHAR2 (500) := LTRIM (RTRIM (SUBSTR (string_in, 1, 500))); /* || I define a function within my function. This module finds the location || in a string of the next NON-BLANK character from the starting location. */ FUNCTION next_nonblank_loc (string_in IN VARCHAR2, start_loc_in IN NUMBER) RETURN NUMBER IS return_value NUMBER := start_loc_in; BEGIN /* || An odd sort of loop: the body of the loop simply moves the pointer || to the next character in the string. The condition in the WHILE loop || boundary performs a substr to compare the "current character" to a || blank. If it is a blank, move to the next character. Otherwise stop || the loop and return that location. */ WHILE SUBSTR (string_in, return_value, 1) = a_blank LOOP return_value := return_value + 1; END LOOP; RETURN return_value END; BEGIN /* || I use two loops to perform the justification. The inner loop adds one || blanks to existing spaces in the string. It quits after it adds a blank || to each candidate area or when then the entire string is justified. || The outer loop starts up the inner loop at the beginning of the string. || This way the additional blanks are spread evenly through the string. */ WHILE len_string < linesize_in -- Outer loop LOOP -- Reset variables for inner loop. start_loc := 1; keep_adding_blanks := TRUE; /* || If I have filled the string or gone through the entire line, || halt this loop and go to the outer loop. */ WHILE len_string < linesize_in AND keep_adding_blanks -- Inner loop LOOP -- Find the location of the next blank. nextblank_loc := INSTR (return_value, a_blank, start_loc); -- If no more blanks, am done with line for this iteration. keep_adding_blanks := nextblank_loc > 0; IF keep_adding_blanks THEN /* || Use SUBSTR to pull apart the string right where the blank was || found and then put the two pieces back together after stuffing || a space between them. Then add 1 to the length and find the || location of the next non-blank character. This new starting || location will be used by INSTR to then find the next blank. */ return_value := SUBSTR (return_value, 1, nextblank_loc) || a_blank || SUBSTR (return_value, nextblank_loc+1); len_string := len_string + 1; start_loc := next_nonblank_loc (return_value, nextblank_loc); END IF; END LOOP; END LOOP; RETURN return_value; END fill_text;