1 /*-------------- Telecommunications & Signal Processing Lab ---------------
2                              McGill University
3 
4 Routine:
5   char *STstrDots (const char Si[], int Maxchar)
6 
7 Purpose:
8   Generate a text with at most Maxchar characters (terminated with ...)
9 
10 Description:
11   This routine copies an input string to an output string.  The output string
12   is at most Maxchar characters long.  If the input string is longer than
13   Maxchar characters long, the algorithm below tries to truncate the line at
14   a blank and add "..." to the output string.  Any non-printable characters
15   are translated to "?".  The intended purpose of this routine is to format
16   error messages.
17 
18   Let the length of the input string be N.  The maximum length of the output
19   string is 80; let M = min(80,Maxchar).
20   1: N <= M
21     The output string is equal to the input string.
22   2: N > M, M >= 20
23     Look for a blank at positions [M-10, M-4] in the input string.  Call the
24     position of the blank i.  Copy the first i+1 characters (includes the
25     blank) of the input string to the output string.  If no blank is found,
26     copy M-3 characters to the output string.  Append "..." to the output
27     string.
28   3: N > M, 6 <= M < 20
29     Copy the first M-3 characters of the input string to the output string.
30     Append "..." to the output string.
31   4: N > M, M < 6
32     Copy the first M characters of the input string to the output string.
33 
34   Examples:
35       input : "It was the best of times, it was the worst"
36                012345678901234567890123456789012345678901
37                0         10       20        30        40
38         M = 60
39       output: "It was the best of times, it was the worst"
40         M = 40
41       output: "It was the best of times, it was the ..."
42         M = 20
43       output: "It was the best ..."
44 
45       input : "Address http://www.TSP.EE.McGill.CA/software.html"
46         M = 30
47       output: "Address http://www.TSP.EE.M..."
48 
49 Parameters:
50  <-   char *STstrDots
51       Output string.  This string is in an internally allocated area and is
52       overwritten each time this routine is called.
53    -> const char Si[]
54       Input character string
55    -> int Maxchar
56       Maximum number of characters (not including the trailing null character)
57       for the output string.
58 
59 Author / revision:
60   P. Kabal  Copyright (C) 2003
61   $Revision: 1.5 $  $Date: 2003/05/09 03:06:42 $
62 
63 -------------------------------------------------------------------------*/
64 
65 #include <ctype.h>
66 #include <string.h>
67 
68 #include <libtsp/nucleus.h>
69 
70 #define MINV(a, b)	(((a) < (b)) ? (a) : (b))
71 #define MAXM		80
72 #define MINM		20
73 
74 static int
75 ST_copyNtr (const char Si[], char So[], int N);
76 
77 
78 char *
STstrDots(const char Si[],int Maxchar)79 STstrDots (const char Si[], int Maxchar)
80 
81 {
82   int nc, i, N, M;
83   static char Line[MAXM+1];
84 
85   N = strlen (Si);
86   M = MINV (MAXM, Maxchar);
87 
88   if (N <= M) {
89     /* No truncation */
90     M = N;
91     nc = N;
92   }
93   else if (M >= MINM) {
94     nc = M - 3;
95     for (i = M-4; i >= M-10; --i) {
96       if (Si[i] == ' ') {
97 	nc = i + 1;
98 	break;
99       }
100     }
101   }
102   else if (M >= 6)
103     nc = M-3;
104   else
105     nc = M;
106 
107 /* Copy characters */
108   ST_copyNtr (Si, Line, nc);
109   if (nc <= M-3)
110     strcpy (&Line[nc], "...");
111 
112   return Line;
113 }
114 
115 /* Copy N characters, translating non-printing characters to '?' */
116 
117 
118 static int
ST_copyNtr(const char Si[],char So[],int N)119 ST_copyNtr (const char Si[], char So[], int N)
120 
121 {
122   int i;
123 
124   for (i = 0; i < N; ++i) {
125     if (isprint ((int) Si[i]))
126       So[i] = Si[i];
127     else
128       So[i] = '?';
129   }
130   So[i] = '\0';
131 
132   return i;
133 }
134 
135