static char rcsid[] = "@(#)$Id: id_phrase.c,v 1.11 2006/07/01 07:37:48 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.11 $   $State: Exp $
 *
 *  Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
 *****************************************************************************/

#include "headers.h"

DEBUG_VAR(Debug,__FILE__,"header");

static unsigned char *s2us P_((char *str));
static unsigned char *s2us(str) 
     char *str;
{
    return (unsigned char *)str;
}

void zero_id_phrase(P)
     struct id_phrase *P;
{
    P->id   = NULL;
    P->text = NULL;
}

void free_id_phrase(P)
     struct id_phrase *P;
{
    if (P->id)
	free(P->id);
    P->id = NULL;
    if (P->text)
	free_string(&(P->text));    
}

int check_8bit_id_phrase(P)
     struct id_phrase *P;
{
    if (P->id && check_8bit_str(P->id))
	return TRUE;
    if (P->text && !can_ascii_string(P->text))
	return TRUE;
    return FALSE;
}

int check_8bit_string(P)
     struct string *P;
{
    if (!P)
	return FALSE;
    if (!can_ascii_string(P))
	return TRUE;
    return FALSE;
}

int check_8bit_str (str)
     char *str;
{
  char *s;

  for (s = str;	*s; s++)
    if (*s & 0x80)
      return HAVE_8BIT;
  return 0;
}

static void do_simple_wrapping1 P_((out_state_t *mailer,  long *pos,
				    char *s, int top_encoding,
				    int lim));
static void do_simple_wrapping1(mailer, pos, s, top_encoding,lim)
     out_state_t *mailer;
     long *pos;
     char *s;
     int top_encoding;
     int lim;
{
    long POS = *pos;
    char *c;
    char *d;

#define LEN (out_state_ftell(mailer)-POS)
#define WRAP print_EOLN(mailer,top_encoding), \
  (POS = out_state_ftell(mailer)), state_putc(' ',mailer)

    for (c = s; *c != '\0'; c=d) {

	if (*c == '\n' || 
	    (whitespace(*c) && (LEN > lim-5))) {
	    WRAP;
	    DPRINT(Debug,9,(&Debug,"[WRAP]\n          "));
	  
	    c++;
	    d = c;
	} else if (whitespace(*c)) {
	    int len;
	    char *e;

	    for (d = c+1; '\0' != *d; d++) {
		if (*d == '\n' || whitespace(*d))
		    break;
	    }

	    len = d-c;
	   
	    if (len + LEN > lim-2 && LEN > 0) {
		WRAP;
		DPRINT(Debug,9,(&Debug,"[WRAP > %d]\n          ",lim-2));

		/* replace space with folding */
		c++;
	    }

	    for (e = c; e < d; e++) {
		state_putc(*e,mailer);
		DPRINT(Debug,9,(&Debug,"%c",*e));
	    }


	} else {

	    state_putc(*c,mailer);
	    DPRINT(Debug,9,(&Debug,"%c",*c));

	    c++;
	    d = c;
	}
    }

    *pos = POS;
}

static void do_simple_wrapping P_((out_state_t *mailer,  long *pos,
				   char *s, int top_encoding));
static void do_simple_wrapping(mailer, pos, s, top_encoding)
     out_state_t *mailer;
     long *pos;
     char *s;
     int top_encoding;
{
    do_simple_wrapping1(mailer,pos,s,top_encoding,79);
}

void write_id_phrase_header (mailer,hdr_name,P, top_encoding, enmime, 
			     hdr_charset)
     out_state_t *mailer;
     CONST char *hdr_name; 
     struct id_phrase * P;
     int top_encoding;
     int enmime;
     charset_t hdr_charset;
{
    long POS = out_state_ftell(mailer);

    char *c;

    if (!P -> id  && !P -> text) {
	DPRINT(Debug,9,
	       (&Debug,"write_id_phrase_header: (%s) -- NONE\n",
		hdr_name));
	return;
    }

    state_puts(hdr_name,mailer);
    state_puts(": ",mailer);

    DPRINT(Debug,9,(&Debug,
		    "write_id_phrase_header: (enmime=%d) %s: \n",
		    enmime,hdr_name));

    DPRINT(Debug,9,(&Debug,
		    "write_id_phrase_header: %s:",hdr_name));

    if (P->id) {
	state_puts(P->id,mailer);
	DPRINT(Debug,9,(&Debug,
			"%s",P->id));
    }

    if (P->text) {
	int X = 0;

	if (string_len(P->text) &&
	    0x0020 == give_unicode_from_string(P->text,0)) {
	    
	    if ((LEN > 60)) {
		WRAP;
		DPRINT(Debug,9,(&Debug,
				"[WRAP]\n          "));
	    } else {
		state_putc(' ',mailer);
		DPRINT(Debug,9,(&Debug," "));
	    }
	    X = 1;
	}

	while (string_len(P->text) > X) {
	    int x = X;
	    struct string * temp = clip_from_string(P->text,&X,900);
	    char * s = string_to_hdr(HDR_PHRASE,temp,
				     hdr_charset,enmime,NULL);
	    DPRINT(Debug,9,(&Debug,"{phrase quoted=%s}\n",s));
	    DPRINT(Debug,9,(&Debug,"\n          [%d..%d] ",x,X));
	    	    
	    do_simple_wrapping(mailer,&POS,s, top_encoding);
	    
	    free(s);
	    free_string(&temp);
	}
    }
    print_EOLN(mailer,top_encoding);    
    DPRINT(Debug,9,(&Debug,"[EOLN]\n"));
}

void write_string_header (mailer,hdr_name,P, top_encoding, enmime, hdr_charset)
     out_state_t *mailer;
     CONST char *hdr_name; 
     struct string * P;
     int top_encoding;
     int enmime;
     charset_t hdr_charset;
{
    long POS = out_state_ftell(mailer);

    char *c;
    int X = 0;

    uint16 was_delim = 0;
	    
    state_puts(hdr_name,mailer);
    state_puts(": ",mailer);

    DPRINT(Debug,9, (&Debug, "write_string_header: (enmime=%d) %s: \n",
		     enmime,hdr_name));

    DPRINT(Debug,9, (&Debug, "write_string_header: %s:",hdr_name));
   
    while (string_len(P) > X) {
	int x = X;

	if (x > 0) {
	    WRAP;
	    DPRINT(Debug,9,(&Debug,
			    "[WRAP]\n          "));
	}

	if (long_encoded_headers) {
	    int slen = LEN;
	    struct string * temp = NULL;
	    char *s;
	    int was_encoded = 0;

	    while (string_len(P) > X) {
		int new_x = X;
	    
		struct string *word = NULL;
		int len1;
		uint16 delim = 0;

		len1 = get_word_from_string(P,&word,&new_x,0,s2us(" "),&delim);
		if (len1 < 1) {
		    /* This handles case where there is no conversion
		       to unicode available
		    */
		    
		    DPRINT(Debug,9, (&Debug, " <<failure: pos %d>>",new_x));
		    
		    free_string(&word);
		    break;
		}
	    
		if (slen + len1 > 70) {
		    free_string(&word);
		    break;
		}
		
		/* Caching delim causes effectively that
		   it is not stored on encoded -> non-encoded
		   transition -- that avoid double space after
		   decoding
		*/


		if (was_delim) {
		    if (!temp)
			temp = new_string(P->string_type);

		    add_unicode_to_string(temp,1,&was_delim);		
		    was_delim = 0;
		}

		append_string(&temp,word);

		free_string(&word);

		slen += len1;   /* Includes delim */
		
		was_delim = delim;

		X = new_x;
	    }

	    if (!temp) {
		X = x;
		goto failure;
	    }

	    s = string_to_hdr(HDR_TEXT,temp,
			      hdr_charset,enmime,&was_encoded);
	    DPRINT(Debug,9, (&Debug,"{text encoded=%s}\n",s));
	    DPRINT(Debug,9, (&Debug,"\n          [%d..%d] ",x,X));
	    

	    /* Hack -- remove extra space (if not encoded) also from raw output */

	    if (' ' == *s)
		do_simple_wrapping1(mailer,&POS,s+1,top_encoding,900);
	    else
		do_simple_wrapping1(mailer,&POS,s,top_encoding,900);

	    /* Remove extra space if just not encoded result */
	    if (!was_encoded)
		was_delim = 0;

	    free(s);
	    free_string(&temp);	    

	} else {
	    struct string * temp;
	    char * s;

	failure:
	    temp = clip_from_string(P,&X,900);
	    s = string_to_hdr(HDR_TEXT,temp,
				     hdr_charset,enmime,NULL);
	    DPRINT(Debug,9, (&Debug,"{text encoded=%s}\n",s));
	    DPRINT(Debug,9, (&Debug,"\n          [%d..%d] ",x,X));
	    
	    do_simple_wrapping(mailer,&POS,s, top_encoding);
	    
	    free(s);
	    free_string(&temp);
	}
    }
    print_EOLN(mailer,top_encoding);    
    DPRINT(Debug,9, (&Debug,"[EOLN]\n"));
}

#undef LEN
#undef WRAP

/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1