/* Copyright 1998 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*---------------------------------------------------------------------------*/ /* File: c.help */ /* Purpose: Routines to deal with help strings. */ /* Author: Richard Leggett */ /* History: 15-Dec-97: RML: Created. */ /* 17-Apr-98: RML: Fixed bug with double \ tokens. */ /* 07-May-98: RML: Code changed to break up long words if won't fit */ /* on one line. */ /*---------------------------------------------------------------------------*/ /* Notes: */ /* - Bug in Font_ScanString means we have to use Font_StringWidth instead. */ /*---------------------------------------------------------------------------*/ #include #include #include #include "swis.h" #include "tboxlibs/gadgets.h" #include "common.h" #include "help.h" #define DesiredAspect 3.5 /* The aspect ratio we want */ #define MaxBoxWidth 1024 /* Maximum width of a help box, in OS units */ #define BackSlash 92 /* Backslash ASCII code */ #define Flag_SplitLine 1 /* Global variables: offset[] - an array of pointers which point to the start of each line in a help message (signified by |M). num_strings - the number of originally specified lines in the help message (ie. NOT the number of lines the message ends up being displayed as). line_spacing - the height of a line of text in the help box font */ static char* offset[256]; static int num_strings; static int line_spacing = 40; /* Temporary value - will be changed later */ /*------------------------------------------------------------------------------------------* * return_string_length * * * * Return the length, in pts, of a string. * * * * In: font = handle of font the string will be displayed in. * * string -> string to find length of. * * * * Returns: length of string if displayed in the specified font. * *------------------------------------------------------------------------------------------*/ int return_string_length(int font, char* string) { int width; int current_font; error_trap(_swix(Font_CurrentFont, _OUT(0), ¤t_font), 0); error_trap(_swix(Font_SetFont, _IN(0), font), 0); error_trap(_swix(Font_StringWidth, _INR(1,5)|_OUT(2), string, 7200000, 7200000, -1, 256, &width), 0); error_trap(_swix(Font_SetFont, _IN(0), current_font), 0); return width; } /*------------------------------------------------------------------------------------------* * count_string_lines * * * * Count the number of lines a string will occupy if it is constrained to a set width. * * Optionally, copy the string into another buffer, null terminating where line breaks * * are necessary. * * * * In: font = handle of fount string will be displayed in. * * string -> the string. * * buffer -> output buffer for null terminated strings, or 0 just to count without * * outputting. * * width = maximum width allowed, in millipoints. * * max_width -> the longest width of any line so far (ie. might be less than 'width'). * * * * Returns: number of lines the string will occupy. * *------------------------------------------------------------------------------------------*/ static int count_string_lines(int font, char *string, int width, char *buffer, int *max_width, int *bytes_out, int *flags) { char *current = string; char *split = 0; char *end = string+(strlen(string)); int lines = 0; int more = 1; int line_width; int current_font; if (bytes_out) *bytes_out = 0; *flags = 0; while (more) { /* Find split and size of split section */ error_trap(_swix(Font_CurrentFont, _OUT(0), ¤t_font), 0); error_trap(_swix(Font_SetFont, _IN(0), font), 0); error_trap(_swix(Font_StringWidth, _INR(1, 5)|_OUTR(1, 2), current, width, 72000, 32, end - current, &split, &line_width), 0); /* If a word won't fit the maximum width (split = current != end), then split word */ if ( (split == current) && (current != end) ) { error_trap(_swix(Font_StringWidth, _INR(1, 5)|_OUTR(1, 2), current, width, 72000, -1, end - current, &split, &line_width), 0); *flags = Flag_SplitLine; } error_trap(_swix(Font_SetFont, _IN(0), current_font), 0); /* Copy the next portion into our output buffer (if one was specified) */ if (buffer) { if (lines == 0) { sprintf(buffer, " "); buffer += 2; *bytes_out += 2; } memcpy(buffer, current, split-current); buffer[split-current] = 0; buffer += (split-current+1); *bytes_out += (split-current+1); } /* Keep track of the largest width string we've had so far */ lines++; if (line_width > *max_width) *max_width = line_width; /* Check for the end of the string */ if ((split >= end) || (split == current)) { more = 0; } else { if (split[0]==' ') split++; current = split; } } return lines; } /*------------------------------------------------------------------------------------------* * break_strings_down * * * * Break the help message down into null terminated strings which represent each line as it * * will appear on text. * * * * In: font = handle of font text will be displayed in. * * width = width text is to fit. * * buffer -> buffer to put strings. * *------------------------------------------------------------------------------------------*/ int break_strings_down(int font, int width, char* buffer) { int lines = 0; int bytes_out = 0; int max_width; int flags; int n; for (n=0; n string in which other string may occur. * * count_string -> string whose occurrance we wish to count. * * * * Returns: number of times the string occurs. * *------------------------------------------------------------------------------------------*/ #if 0 static int count_occurrences(char *string, char* count_string) { char *next = string; int lines = 1; while (next != 0) { next = strstr(next, count_string); if (next++) lines++; } return lines; } #endif /*------------------------------------------------------------------------------------------* * translate_help_string * * * * Take a help string, de-tokenise and fill offset[] with pointers to each line of text (as * * specified in the help string by |M). * * * * In: help_string -> initial string * * new_string -> translated string * * * * Globals: offset[], num_strings * *------------------------------------------------------------------------------------------*/ int translate_help_string(char* help_string, char* new_string, int length) { char token[4]; int m = 0; int n; num_strings = 0; offset[num_strings++] = new_string; /* Loop through help string searching for tokens (\T) and new lines */ for (n=0; n= ' ') new_string[m++]=help_string[n]; } } /* Terminate the string */ new_string[m] = 0; return num_strings; } /*------------------------------------------------------------------------------------------* * try_fitting_to_whole_line * * * * The first of two attempts to choose box size. This takes each line in turn and uses it's * * width to try to fit the other lines. The size of the resultant box is calculated and * * from that, it's aspect ratio. The best aspect ratio is kept track of. * *------------------------------------------------------------------------------------------*/ static int try_fitting_to_whole_line(int font_handle, double* return_aspect, int* return_width, int* return_lines) { double aspect = -200; int max_width; int largest; int height; int width; int lines; int more; int flags; int split_line; int return_split = 1; int nearer; int n; int m; _swix(Font_Converttopoints, _INR(1,2)|_OUT(1), MaxBoxWidth, 0, &max_width); for (n=0; nmax_width) width=max_width; /* How many lines will be used for this width? */ split_line = 0; for (m=0; m help text. * * font_handle -> handle of font that text will be displayed in. * * * * Returns: Width to constrain text to. * *------------------------------------------------------------------------------------------*/ int choose_box_width(int font_handle, int* box_width, int* box_height) { double aspect = -100; int width = MaxBoxWidth; int lines = num_strings; try_fitting_to_whole_line(font_handle, &aspect, &width, &lines); *box_height = lines * line_spacing; error_trap(_swix(Font_ConverttoOS, _INR(1,2)|_OUT(1), width, 0, box_width), 0); *box_height += 16; *box_width += 44; return width; } /*------------------------------------------------------------------------------------------* * help_font_initialise * * * * Set up a few font bits and pieces. * *------------------------------------------------------------------------------------------*/ int help_font_initialise(char* fontname, int fontsize, int* ls) { int font_handle; int ymin; int ymax; error_trap(_swix(Font_FindFont, _INR(1,5)|_OUT(0), fontname, fontsize * 16, fontsize * 16, 0, 0, &font_handle), 0); error_trap(_swix(Font_ReadInfo, _IN(0)|_OUT(2)|_OUT(4), font_handle, &ymin, &ymax), 0); line_spacing = ymax-ymin; *ls = line_spacing; return font_handle; }