"nimdez" <ni****@yahoo.com> wrote in message
xprintf("%=10s %=25s %=15s\n", pszCol1, pszCol2, pszCol3)
The problem is it is difficult to pass most of the code on to vsprintf() to
do the work. This is because of the nature of variadic functions.
However this might be useful to you. (Tested slightly).
/*
print a series of strings and a format string, wrapping
to preserve columns.
Currently only the %<width>s format is supported
*/
void colprint(char *fmt, ...)
{
int nargs = 0;
char ***column;
int *tabs;
int *widths;
int i;
int ii;
int Npercent = 0;
int col = 0;
int width;
char *end;
char *str;
va_list vargs;
/*
In order to simplify the code, allocate enough space
here based on number % signs passed
*/
for(i=0;fmt[i];i++)
if(fmt[i] == '%')
Npercent++;
column = malloc(Npercent * sizeof(char **));
tabs = malloc(Npercent * sizeof(int));
widths = malloc(Npercent *sizeof(int));
if(!column || !tabs || !widths)
goto cleanup;
va_start(vargs, fmt);
while(*fmt)
{
if(*fmt == '%')
{
switch( getfieldtype(fmt) )
{
case '%':
putchar('%');
fmt += 2;
break;
case 's':
width = strtol(fmt+1, &end, 10);
tabs[nargs] = col;
widths[nargs] = width;
str = va_arg(vargs, char *);
column[nargs] = strwrap(str, width);
if(!column[nargs])
goto cleanup;
for(i=0;column[nargs][0][i];i++)
{
putchar( column[nargs][0][i] );
col++;
}
while(i<width)
{
putchar(' ');
col++;
i++;
}
nargs++;
while(*fmt != 's')
fmt++;
break;
/* add other fields here if you wish to support them */
default:
fprintf(stderr, "Format %c not recognised\n", getfieldtype(fmt));
return;
}
}
else
{
putchar(*fmt);
col++;
fmt++;
}
}
va_end(vargs);
printcolumns(column, tabs, widths, nargs);
cleanup:
for(i=0;i<nargs;i++)
{
for(ii=0;column[i][ii];ii++)
free(column[i][ii]);
free(column[i]);
}
if(column)
free(column);
if(tabs)
free(tabs);
if(widths)
free(widths);
}
/*
get the type of field we are passed.
*/
char getfieldtype(char *fmt)
{
assert(*fmt == '%');
fmt++;
if(*fmt == '%')
return '%';
while(*fmt && !isalpha(*fmt))
fmt++;
return *fmt;
}
/*
Prints the wrapped text in the right column.
cols - pointer to list of wrapped text
tabs - tab offset of each column
width - widths of each column
ncols - number of columns passed
*/
void printcolumns(char ***cols, int *tabs, int *widths, int ncols)
{
int i;
int ii;
int iii;
int *coldepth;
int maxdepth = 0;
int col;
coldepth = malloc(ncols * sizeof(int));
if(!coldepth)
return;
/* find the depth of each column (NULL-terminated list)
for(i=0;i<ncols;i++)
{
coldepth[i] = 0;
while(cols[i][coldepth[i]])
coldepth[i]++;
}
/* find the maximum depth */
for(i=0;i<ncols;i++)
if(maxdepth < coldepth[i])
maxdepth = coldepth[i];
/* print out the column */
for(i=1;i<maxdepth;i++)
{
col = 0;
for(ii=0;ii<ncols;ii++)
{
while(col < tabs[ii])
{
putchar(' ');
col++;
}
if(coldepth[ii] > i)
{
for(iii=0;cols[ii][i][iii];iii++)
{
putchar( cols[ii][i][iii] );
col++;
}
}
while(col < tabs[ii] + widths[ii])
{
putchar(' ');
col++;
}
}
putchar('\n');
}
free(coldepth);
}
/*
string-wrapping function.
Params: str - string to wrap
len - maximum length of column
Returns: NULL-terminated list of truncated strings
*/
char **strwrap(const char *str, int len)
{
char **answer = 0;
char **temp;
char *buff;
int nlines = 0;
int i;
while(*str)
{
temp = realloc(answer, (nlines + 2) * sizeof(char *));
if(!temp)
{
for(i=0;i<nlines;i++)
free(answer[i]);
free(answer);
return 0;
}
answer = temp;
buff = malloc(len+1);
if(!buff)
{
for(i=0;i<nlines;i++)
free(answer[i]);
free(answer);
return 0;
}
wrapline(buff, str, len);
answer[nlines++] = buff;
str += strlen(buff);
}
answer[nlines] = 0;
return answer;
}
/*
wrap a line of text
ret - return pointer for line
str - text to wrap
len - maximum length of line
*/
void wrapline(char *ret, const char *str, int len)
{
char *end;
if(len > (int) strlen(str))
len = strlen(str);
if(len < 1)
{
strcpy(ret, "");
return;
}
end = strchr(str, '\n');
if(end && end - str < len)
{
memcpy(ret, str, end - str + 1);
ret[end-str+1] = 0;
return;
}
memcpy(ret, str, len);
end = &ret[len-1];
if(str[len] != 0)
while(end > ret && !isspace(*end))
end--;
if(end > ret)
end[1] = 0;
else
ret[len] = 0;
}