#include "billingkom.h"

long msglinesonscreen;

void stbprintf(long numlines,char *fmt,...)
{
   va_list args;
   long c;
   char buf[200];

   va_start(args, fmt);
   vfprintf(ownstdout,fmt,args);
   va_end(args);

   for(c=0;fmt[c];c++)
      if(fmt[c]=='\n')
      {
         linesonscreen++;
         msglinesonscreen++;
      }

   if(linesonscreen >= cfg_Lines-2 && ownstdout == stdout)
   {
      sprintf(buf,strings[STR_PRESSRETURNLINES],msglinesonscreen,numlines);
      ospause(buf);
      linesonscreen=0;
   }
}

long countlines(char *text)
{
   long c,textpos,lastspace,numlines;

   textpos=0;
   lastspace=0;

   numlines=0;

   while(text[textpos]!=0)
   {
      lastspace=0;
      c=0;

      while(c<currentwidth && text[textpos+c]!=0 && text[textpos+c]!='\n')
      {
         if(text[textpos+c]==32) lastspace=c;
         c++;
      }

      if(c==currentwidth && lastspace)
      {
         textpos+=lastspace+1;
      }
      else
      {
         if(text[textpos+c]=='\n') c++;
         textpos+=c;
      }
      numlines++;
   }
   return(numlines);
}

#define IKSAS(a) (a=='x' || a=='X' || a==39)

void EsperantizeString(char *s)
{
	int i,j;

	for (i=0,j=0;s[i] != '\0';i++)
   {
      if(s[i]=='^')
      {
   		switch(s[i+1])
	   	{
		   	case 'c': s[j++]=230; i++; break;
			   case 'g': s[j++]=248; i++; break;
   			case 'h': s[j++]=182; i++; break;
	   		case 'j': s[j++]=188; i++; break;
		   	case 's': s[j++]=254; i++; break;
			   case 'u': s[j++]=253; i++; break;

   			case 'C': s[j++]=198; i++; break;
	   		case 'G': s[j++]=216; i++; break;
		   	case 'H': s[j++]=166; i++; break;
			   case 'J': s[j++]=172; i++; break;
   			case 'S': s[j++]=222; i++; break;
	   		case 'U': s[j++]=221; i++; break;

		   	default: s[j++] = s[i]; break;
   		}
      }
      else
      {
   		switch(s[i])
	   	{
		   	case 'c': if (IKSAS(s[i+1])) {s[j++]=230; i++; break;} else {s[j++] = s[i];break;}
			   case 'g': if (IKSAS(s[i+1])) {s[j++]=248; i++; break;} else {s[j++] = s[i];break;}
   			case 'h': if (IKSAS(s[i+1])) {s[j++]=182; i++; break;} else {s[j++] = s[i];break;}
	   		case 'j': if (IKSAS(s[i+1])) {s[j++]=188; i++; break;} else {s[j++] = s[i];break;}
		   	case 's': if (IKSAS(s[i+1])) {s[j++]=254; i++; break;} else {s[j++] = s[i];break;}
			   case 'u': if (IKSAS(s[i+1])) {s[j++]=253; i++; break;} else {s[j++] = s[i];break;}

   			case 'C': if (IKSAS(s[i+1])) {s[j++]=198; i++; break;} else {s[j++] = s[i];break;}
	   		case 'G': if (IKSAS(s[i+1])) {s[j++]=216; i++; break;} else {s[j++] = s[i];break;}
		   	case 'H': if (IKSAS(s[i+1])) {s[j++]=166; i++; break;} else {s[j++] = s[i];break;}
			   case 'J': if (IKSAS(s[i+1])) {s[j++]=172; i++; break;} else {s[j++] = s[i];break;}
   			case 'S': if (IKSAS(s[i+1])) {s[j++]=222; i++; break;} else {s[j++] = s[i];break;}
	   		case 'U': if (IKSAS(s[i+1])) {s[j++]=221; i++; break;} else {s[j++] = s[i];break;}

		   	default: s[j++] = s[i]; break;
   		}
      }
   }
	s[j] = '\0';
}

char stylebuf[200];
char stylebufout[2000];

void showtextblock(char *text,char *group,char *folder)
{
   long c,d,emptylines,textpos,lastspace,numlines;
   char buf[200],quotebuf[10],cfggroupname[100];
   bool quote,quoteoff;
   char *quotestart,*quoteend,*quotechars,*cfg;

   quotechars=":>";

   if(group && group[0])
   {
      strcpy(cfggroupname,group);
   }
   else
   {
      strcpy(cfggroupname,"Mail.");

      if(folder && folder[0])
         strcat(cfggroupname,folder);
   }

   if((cfg=umsgetgroupconfig(cfggroupname,"QuoteChars")))
      quotechars=cfg;

   numlines=countlines(text);

   msglinesonscreen=0;

   brk=FALSE;
   quote=FALSE;
   textpos=0;
   emptylines=0;
   lastspace=0;

   while(text[textpos]!=0 && !brk)
   {
      lastspace=0;
      c=0;
      quoteoff=FALSE;

      while(c<currentwidth && text[textpos+c]!=0 && text[textpos+c]!='\n')
      {
         if(text[textpos+c]==32) lastspace=c;
         c++;
      }

      if(c==currentwidth && lastspace)
      {
         /* Wrap */
         strncpy(buf,&text[textpos],(size_t)lastspace);
         buf[lastspace]=0;
         textpos+=lastspace+1;
      }
      else
      {
         /* Full line */
         strncpy(buf,&text[textpos],(size_t)c);
         buf[c]=0;
         if(text[textpos+c]=='\n') c++;
         textpos+=c;

         quoteoff=TRUE; /* Turn off quote after this line */
      }

      if(buf[0]==0)
      {
         emptylines++;
      }
      else
      {
         if(emptylines)
         {
            for(c=0;c<emptylines && !brk;c++)
               stbprintf(numlines,"\n");
         }

         emptylines=0;

         if(!brk)
         {
            mystrncpy(quotebuf,buf,9);

            for(c=0;c<strlen(quotechars);c++)
               if(strchr(quotebuf,quotechars[c])) quote=TRUE;

            quotestart="";
            quoteend="";

            if(quote && ownstdout==stdout && flags[CFG_HILIGHTQUOTE].set)
            {
               quotestart="\x1b[32m";
               quoteend="\x1b[0m";
            }

            strcpy(stylebufout,buf);

            if(flags[CFG_TEXTSTYLES].set && ownstdout==stdout)
            {
               char *slut,*startkod;

               char *st_stylechars  = "*/_#";
               char *st_nonintro    = " ^+\\|?=([{&%$§\"!:";
               char *st_whitespace  = " ([{\"'&+*_#/";
               char *st_term        = " )]}.,:;+-='&\"!?*_#/";

               for(c=0;buf[c];c++)
                  stylebuf[c]=0;

               for(c=0;buf[c];c++)
               {
                  if(strchr(st_stylechars,buf[c]))
                  {
                     /* We have a style character */

                     if(c==0 || strchr(st_whitespace,buf[c-1]))
                     {
                        /* Nothing or allowed character before it */

                        if(!strchr(st_nonintro,buf[c+1]))
                        {
                           /* Not forbidden character after it */

                           if((slut=strchr(&buf[c+1],buf[c])) && (strchr(st_term,*(slut+1)) || *(slut+1)==0))
                           {
                              /* Has matching character with nothing or allowed character afterwards */

                              stylebuf[c]=buf[c];
                              stylebuf[slut-buf]='0';
                           }
                        }
                     }
                  }
               }

               d=0;

               for(c=0;buf[c];c++)
               {
                  if(stylebuf[c])
                  {
                     if(stylebuf[c]=='0')
                     {
                        strcpy(&stylebufout[d],"\x1b[0m");
                        d+=4;

                        strcpy(&stylebufout[d],quotestart);
                        d+=strlen(quotestart);
                     }
                     else
                     {
                        switch(stylebuf[c])
                        {
                           case '*': startkod="\x1b[1m";
                                     break;

                           case '/': startkod="\x1b[3m";
                                     break;

                           case '_': startkod="\x1b[4m";
                                     break;

                           case '#': startkod="\x1b[33m";
                                     break;
                        }

                        strcpy(&stylebufout[d],startkod);
                        d+=strlen(startkod);
                     }
                  }
                  else
                  {
                     stylebufout[d++]=buf[c];
                  }
               }

               stylebufout[d]=0;
            }

            if(flags[CFG_ESPERANTO].set && ownstdout==stdout)
               EsperantizeString(stylebufout);

            stbprintf(numlines,"%s%s%s\n",quotestart,stylebufout,quoteend);

            if(quoteoff)
               quote=FALSE;
         }
      }
   }

   if(textpos>0 && text[textpos-1]!='\n')
      stbprintf(numlines,"\n");

   if(cfg)
      UMSFreeConfig(login,cfg);
}


void showmessage(long num)
{
   char *fields[128];
   char fromname[200],toname[200],groupname[200],replyname[200];
   struct MessageInfo msginfo;
   long res,c;
   char *text;

   brk=FALSE;

   res=UMSReadMsgTags(login,UMSTAG_RMsgNum,       num,
                            UMSTAG_RTextFields,   fields,
                            UMSTAG_RReadAll,      1,
                            UMSTAG_RMsgInfo,      &msginfo,
                            TAG_DONE);

   if(!res)
   {
      printf(strings[STR_TEXTNRNOTEXIST],num);
      return;
   }

   if(flags[CFG_CLEARSCREEN].set && ownstdout == stdout)
      printf("\x0c");

   linesonscreen=0;

   makegroup(groupname,fields[UMSCODE_Group],fields[UMSCODE_Folder]);
   makename(fromname,fields[UMSCODE_FromName],fields[UMSCODE_FromAddr]);

   if(flags[CFG_SIGNALTOYOU].set && msginfo.msgi_ChainUp)
   {
      long upuserflags;

      res=UMSReadMsgTags(login,UMSTAG_RMsgNum,   msginfo.msgi_ChainUp,
                                UMSTAG_RUserFlags,&upuserflags,
                                TAG_DONE);

      if(res)
      {
         if(upuserflags & UMSUSTATF_Owner)
            printf("\x07");

         UMSFreeMsg(login,msginfo.msgi_ChainUp);
      }
   }

   ownprintf(strings[STR_READNUMBER],
      num,
      fromname);

   if(!fields[UMSCODE_Group])
   {
      makename(toname,fields[UMSCODE_ToName],fields[UMSCODE_ToAddr]);
      ownprintf(strings[STR_READISMAILTO],toname);

      if(msginfo.msgi_SoftLink)
      {
         long templink,oldlink,startlink;

         startlink=num;
         templink=msginfo.msgi_SoftLink;
         oldlink=0;

         while(templink != startlink && templink!=oldlink)
         {
            char *to,*toaddr;

            if(brk)
            {
               printf("\n");
               printf(strings[STR_BREAK]);
               UMSFreeMsg(login,num);
               return;
            }

            oldlink=templink;

            res=UMSReadMsgTags(login,UMSTAG_RToName,   &to,
                                     UMSTAG_RToAddr,   &toaddr,
                                     UMSTAG_RMsgNum,   templink,
                                     UMSTAG_RSoftLink, &templink,
                                     TAG_DONE);

            if(res)
            {
               makename(toname,to,toaddr);
               ownprintf(strings[STR_READCOPYTO],toname);
               UMSFreeMsg(login,oldlink);
            }
         }
      }
   }
   else
   {
      if(msginfo.msgi_ChainUp)
      {
         char *From;

         res=UMSReadMsgTags(login,UMSTAG_RMsgNum,   msginfo.msgi_ChainUp,
                                  UMSTAG_RFromName, &From,
                                  TAG_DONE);
         if(res)
         {
            ownprintf(strings[STR_READISCOMMENTNR],msginfo.msgi_ChainUp,From);
            UMSFreeMsg(login,msginfo.msgi_ChainUp);
         }
      }
      else
      {
         if(fields[UMSCODE_ReferID] && fields[UMSCODE_ToName])
            ownprintf(strings[STR_READISCOMMENT],fields[UMSCODE_ToName]);
      }

      ownprintf(strings[STR_READRECEIVER],groupname);

      if(msginfo.msgi_HardLink)
      {
         long templink,oldlink,startlink;

         startlink=num;
         templink=msginfo.msgi_HardLink;
         oldlink=0;

         while(templink != startlink && templink != oldlink)
         {
            char *group,*folder;
            char groupname[200];

            if(brk)
            {
               printf("\n");
               printf(strings[STR_BREAK]);
               UMSFreeMsg(login,num);
               return;
            }

            oldlink=templink;

            res=UMSReadMsgTags(login,UMSTAG_RGroup,    &group,
                                     UMSTAG_RFolder,   &folder,
                                     UMSTAG_RMsgNum,   templink,
                                     UMSTAG_RHardLink, &templink,
                                     TAG_DONE);

            if(res)
            {
               makegroup(groupname,group,folder);
               ownprintf(strings[STR_READRECEIVER],groupname);
               UMSFreeMsg(login,oldlink);
            }
         }
      }
   }

   ownprintf(strings[STR_READDATE],
      fields[UMSCODE_CreationDate]);

   if(fields[UMSCODE_ReplyName])
   {
      makename(replyname,fields[UMSCODE_ReplyName],fields[UMSCODE_ReplyAddr]);
      ownprintf(strings[STR_READREPLYTO],replyname);
   }

   if(fields[UMSCODE_Organization] && !flags[CFG_HIDEORGANIZATION].set)
      ownprintf(strings[STR_READORGANIZATION],fields[UMSCODE_Organization]);

   if(fields[UMSCODE_ReplyGroup])
   {
      if(stricmp(fields[UMSCODE_ReplyGroup],"poster")==0)
      {
         ownprintf(strings[STR_FUPTOPOSTER]);
      }
      else
      {
         makegroup(groupname,fields[UMSCODE_ReplyGroup],"");
         ownprintf(strings[STR_READFOLLOWUPTO],groupname);
      }
   }

   if(fields[UMSCODE_Distribution] && !flags[CFG_HIDEDISTRIBUTION].set)
      ownprintf(strings[STR_READDISTRIBUTION],fields[UMSCODE_Distribution]);

   ownprintf(strings[STR_READSUBJECT],fields[UMSCODE_Subject]);

   if(fields[UMSCODE_Attributes])
      ownprintf(strings[STR_READATTRIBUTES],fields[UMSCODE_Attributes]);

   if(msginfo.msgi_UserStatus & UMSUSTATF_Archive)
      ownprintf(strings[STR_READISARCHIVED]);

   if(msginfo.msgi_UserStatus & UMSUSTATF_PostPoned)
      ownprintf(strings[STR_READISPOSTPONED]);

   if(msginfo.msgi_UserStatus & UMSUSTATF_Selected)
      ownprintf(strings[STR_READISSELECTED]);

   if(msginfo.msgi_UserStatus & UMSUSTATF_Filtered)
      ownprintf(strings[STR_READISFILTERED]);

   if(msginfo.msgi_UserStatus & UMSUSTATF_Junk)
      ownprintf(strings[STR_READISJUNK]);

   if(msginfo.msgi_GlobalStatus & UMSGSTATF_Parked)
      ownprintf(strings[STR_READISPARKED]);

   if(msginfo.msgi_GlobalStatus & UMSGSTATF_HasFile)
      printf(strings[STR_READENCLOSEDFILE],fields[UMSCODE_FileName]);

   if(flags[CFG_SUBJECTLINE].set)
   {
      for(c=0;c<currentwidth;c++)
         ownprintf("-");
   }

   ownprintf("\n");

   text=fields[UMSCODE_MsgText];
   if(!text) text="";

   showtextblock(text,fields[UMSCODE_Group],fields[UMSCODE_Folder]);

   if(brk)
   {
      printf("\n");
      printf(strings[STR_BREAK]);
   }
   else
   {
      long tempchain,oldchain;

      ownprintf(strings[STR_READEND],num,fields[UMSCODE_FromName],groupname);

      tempchain=msginfo.msgi_ChainDn;

      while(tempchain)
      {
         char *Group,*Folder,*FromName;
         long userflags;

         oldchain=tempchain;

         res=UMSReadMsgTags(login,UMSTAG_RGroup,    &Group,
                                  UMSTAG_RFolder,   &Folder,
                                  UMSTAG_RMsgNum,   tempchain,
                                  UMSTAG_RChainRt,  &tempchain,
                                  UMSTAG_RFromName, &FromName,
                                  UMSTAG_RUserFlags,&userflags,
                                  TAG_DONE);

         if(!FromName) FromName="";

         if(res)
         {
            makegroup(groupname,Group,Folder);
            ownprintf(" ");

            if(userflags & UMSUSTATF_Old)
               ownprintf(strings[STR_READHASREADCOMMENT],groupname,oldchain,FromName);

            else
               ownprintf(strings[STR_READHASCOMMENT],groupname,oldchain,FromName);

            UMSFreeMsg(login,oldchain);
         }
      }
   }

   UMSFreeMsg(login,num);
   lastread=num;
}

void addbackarray(long num)
{
   long c;

   if(backarraynum == BACKARRAYSIZE)
   {
      for(c=0;c<BACKARRAYSIZE-1;c++)
         backarray[c]=backarray[c+1];

      backarray[BACKARRAYSIZE-1]=num;
   }
   else if(backarraynum<BACKARRAYSIZE)
   {
      backarray[backarraynum++]=num;
   }

   backpos=backarraynum;
}

void addreadarray(long num)
{
   long tempchain,nextchain,userflags,res;
   char lastmsgid[200],*msgid;

   /* Get first */

   res=UMSReadMsgTags(login,UMSTAG_RMsgNum,   num,
                            UMSTAG_RChainDn,  &nextchain,
                            TAG_DONE);

   if(!res)
      return;

   UMSFreeMsg(login,num);

   /* Go to last in chain */

   do
   {
      tempchain=nextchain;

      res=UMSReadMsgTags(login,UMSTAG_RMsgNum,   tempchain,
                               UMSTAG_RChainRt,  &nextchain,
                               UMSTAG_RUserFlags,&userflags,
                               TAG_DONE);

      if(!res)
         return;

      UMSFreeMsg(login,tempchain);

   } while(nextchain);

   /* If we don't read them backwards, they will end up in the wrong order in readarray */

   nextchain=tempchain;
   lastmsgid[0]=0;

   while(nextchain)
   {
      tempchain=nextchain;

      res=UMSReadMsgTags(login,UMSTAG_RMsgNum,   tempchain,
                               UMSTAG_RChainLt,  &nextchain,
                               UMSTAG_RMsgID,    &msgid,
                               UMSTAG_RUserFlags,&userflags,
                               TAG_DONE);

      if(!res)
         return;

      if((!(userflags & UMSUSTATF_Old)) && stricmp(msgid,lastmsgid)!=0)
      {
        if(readarraynum < READARRAYSIZE)
            readarray[readarraynum++]=tempchain;
      }

      mystrncpy(lastmsgid,msgid,200);
      UMSFreeMsg(login,tempchain);
   }
}

void showmessageverbose(long num)
{
   char *fields[128];
   char fromname[200],toname[200];
   struct MessageInfo msginfo;
   long c,res;
   char *text;

   brk=FALSE;

   res=UMSReadMsgTags(login,UMSTAG_RMsgNum,       num,
                            UMSTAG_RTextFields,   fields,
                            UMSTAG_RReadAll,      1,
                            UMSTAG_RMsgInfo,      &msginfo,
                            UMSTAG_RDateStyle,    1,
                            TAG_DONE);

   if(!res)
   {
      printf(strings[STR_TEXTNRNOTEXIST],num);
      return;
   }

   linesonscreen=0;

   ownprintf("Number: %ld\n",num);

   makename(fromname,fields[UMSCODE_FromName],fields[UMSCODE_FromAddr]);
   ownprintf("From: %s\n",fromname);

   if(fields[UMSCODE_ToName])
   {
      makename(toname,fields[UMSCODE_ToName],fields[UMSCODE_ToAddr]);
      ownprintf("To: %s\n",toname);
   }

   if(fields[UMSCODE_LogicalToName])
   {
      makename(toname,fields[UMSCODE_LogicalToName],fields[UMSCODE_LogicalToAddr]);
      ownprintf("LogicalTo: %s\n",toname);
   }

   if(fields[UMSCODE_Group])
      ownprintf("Group: %s\n",fields[UMSCODE_Group]);

   if(!fields[UMSCODE_Group])
   {
      if(msginfo.msgi_SoftLink)
      {
         long templink,oldlink,startlink;

         startlink=num;
         templink=msginfo.msgi_SoftLink;

         while(templink != startlink)
         {
            char *to,*toaddr;

            if(brk)
            {
               printf("\n");
               printf(strings[STR_BREAK]);
               UMSFreeMsg(login,num);
               return;
            }

            oldlink=templink;

            res=UMSReadMsgTags(login,UMSTAG_RToName,   &to,
                                     UMSTAG_RToAddr,   &toaddr,
                                     UMSTAG_RMsgNum,   templink,
                                     UMSTAG_RSoftLink, &templink,
                                     TAG_DONE);

            if(res)
            {
               makename(toname,to,toaddr);
               ownprintf("Copy-To: %s\n",toname);
               UMSFreeMsg(login,oldlink);
            }
         }
      }
   }
   else
   {
      if(msginfo.msgi_HardLink)
      {
         long templink,oldlink,startlink;

         startlink=num;
         templink=msginfo.msgi_HardLink;

         while(templink != startlink)
         {
            char *group;

            if(brk)
            {
               printf("\n");
               printf(strings[STR_BREAK]);
               UMSFreeMsg(login,num);
               return;
            }

            oldlink=templink;

            res=UMSReadMsgTags(login,UMSTAG_RGroup,    &group,
                                     UMSTAG_RMsgNum,   templink,
                                     UMSTAG_RHardLink, &templink,
                                     TAG_DONE);

            if(res)
            {
               ownprintf("Group: %s\n",group);
               UMSFreeMsg(login,oldlink);
            }
         }
      }
   }

   if(fields[UMSCODE_Folder])
      ownprintf("Folder: %s\n",fields[UMSCODE_Folder]);

   ownprintf("Subject: %s\n",fields[UMSCODE_Subject]);

   if(fields[UMSCODE_CreationDate])
      ownprintf("CreationDate: %s\n",fields[UMSCODE_CreationDate]);

   if(fields[UMSCODE_ReceiveDate])
      ownprintf("ReceiveDate: %s\n",fields[UMSCODE_ReceiveDate]);

   if(fields[UMSCODE_ReplyName])
   {
      makename(fromname,fields[UMSCODE_ReplyName],fields[UMSCODE_ReplyAddr]);
      ownprintf("ReplyName: %s\n",fromname);
   }

   if(fields[UMSCODE_ReplyGroup])
      ownprintf("ReplyGroup: %s\n",fields[UMSCODE_ReplyGroup]);

   if(fields[UMSCODE_Organization])
      ownprintf("Organization: %s\n",fields[UMSCODE_Organization]);

   if(fields[UMSCODE_Distribution])
      ownprintf("Distribution: %s\n",fields[UMSCODE_Distribution]);

   if(fields[UMSCODE_Newsreader])
      ownprintf("Newsreader: %s\n",fields[UMSCODE_Newsreader]);

   ownprintf("Subject: %s\n",fields[UMSCODE_Subject]);

   if(fields[UMSCODE_Attributes])
      ownprintf("Attributes: %s\n",fields[UMSCODE_Attributes]);

   if(fields[UMSCODE_RfcAttr])
      ownprintf("RfcAttr: %s\n",fields[UMSCODE_RfcAttr]);

   if(fields[UMSCODE_FtnAttr])
      ownprintf("FtnAttr: %s\n",fields[UMSCODE_FtnAttr]);

   if(fields[UMSCODE_ZerAttr])
      ownprintf("ZerAttr: %s\n",fields[UMSCODE_ZerAttr]);

   if(fields[UMSCODE_MausAttr])
      ownprintf("MausAttr: %s\n",fields[UMSCODE_MausAttr]);

   if(fields[UMSCODE_MsgID])
      ownprintf("MsgID: %s\n",fields[UMSCODE_MsgID]);

   if(fields[UMSCODE_FidoID])
      ownprintf("FidoID: %s\n",fields[UMSCODE_FidoID]);

   if(fields[UMSCODE_MausID])
      ownprintf("MausID: %s\n",fields[UMSCODE_MausID]);

   if(fields[UMSCODE_ReferID])
      ownprintf("ReferID: %s\n",fields[UMSCODE_ReferID]);

   if(fields[UMSCODE_ErrorText])
      ownprintf("ErrorText: %s\n",fields[UMSCODE_ErrorText]);

   if(fields[UMSCODE_FileName])
      ownprintf("FileName: %s\n",fields[UMSCODE_FileName]);

   if(fields[UMSCODE_TempFileName])
      ownprintf("TempFileName: %s\n",fields[UMSCODE_TempFileName]);

   if(msginfo.msgi_UserStatus)
   {
      ownprintf("UserStatus:");

      if(msginfo.msgi_UserStatus & UMSUSTATF_Archive)
         ownprintf(" Archive");

      if(msginfo.msgi_UserStatus & UMSUSTATF_Junk)
         ownprintf(" Junk");

      if(msginfo.msgi_UserStatus & UMSUSTATF_PostPoned)
         ownprintf(" PostPoned");

      if(msginfo.msgi_UserStatus & UMSUSTATF_Selected)
         ownprintf(" Selected");

      if(msginfo.msgi_UserStatus & UMSUSTATF_Filtered)
         ownprintf(" Filtered");

      if(msginfo.msgi_UserStatus & UMSUSTATF_Old)
         ownprintf(" Old");

      if(msginfo.msgi_UserStatus & UMSUSTATF_WriteAccess)
         ownprintf(" WriteAccess");

      if(msginfo.msgi_UserStatus & UMSUSTATF_ReadAccess)
         ownprintf(" ReadAccess");

      if(msginfo.msgi_UserStatus & UMSUSTATF_ViewAccess)
         ownprintf(" ViewAccess");

      if(msginfo.msgi_UserStatus & UMSUSTATF_Owner)
         ownprintf(" Owner");

      ownprintf("\n");
   }

   if(msginfo.msgi_GlobalStatus)
   {
      ownprintf("GlobalStatus:");

      if(msginfo.msgi_GlobalStatus & UMSGSTATF_Deleted)
         ownprintf(" Deleted");

      if(msginfo.msgi_GlobalStatus & UMSGSTATF_Expired)
         ownprintf(" Expired");

      if(msginfo.msgi_GlobalStatus & UMSGSTATF_Exported)
         ownprintf(" Exported");

      if(msginfo.msgi_GlobalStatus & UMSGSTATF_Orphan)
         ownprintf(" Orphan");

      if(msginfo.msgi_GlobalStatus & UMSGSTATF_Link)
         ownprintf(" Link");

      if(msginfo.msgi_GlobalStatus & UMSGSTATF_HardLink)
         ownprintf(" HardLink");

      if(msginfo.msgi_GlobalStatus & UMSGSTATF_Parked)
         ownprintf(" Parked");

      if(msginfo.msgi_GlobalStatus & UMSGSTATF_HasFile)
         ownprintf(" HasFile");

      ownprintf("\n");
   }

   if(msginfo.msgi_HardLink)
      ownprintf("HardLink: %ld\n",msginfo.msgi_HardLink);

   if(msginfo.msgi_SoftLink)
      ownprintf("SoftLink: %ld\n",msginfo.msgi_SoftLink);

   ownprintf("ChainUp: %ld ChainLt: %ld ChainRt: %ld ChainDn: %ld\n",
      msginfo.msgi_ChainUp,
      msginfo.msgi_ChainLt,
      msginfo.msgi_ChainRt,
      msginfo.msgi_ChainDn);

   if(flags[CFG_SUBJECTLINE].set)
   {
      for(c=0;c<currentwidth;c++)
         ownprintf("-");
   }

   ownprintf("\n");

   text=fields[UMSCODE_MsgText];
   if(!text) text="";

   showtextblock(text,fields[UMSCODE_Group],fields[UMSCODE_Folder]);

   if(fields[UMSCODE_Comments] && !brk)
   {
      ownprintf("\n");
      ownprintf("Comments: \n");
      ownprintf("\n");
      showtextblock(fields[UMSCODE_Comments],fields[UMSCODE_Group],fields[UMSCODE_Folder]);
   }

   if(brk)
   {
      printf("\n");
      printf(strings[STR_BREAK]);
   }
   UMSFreeMsg(login,num);
}

void kom_nextreply(char *arg,char *data)
{
   long num;

   if(readarraynum == 0)
   {
      printf(strings[STR_NOMORECOMMENTS]);
   }
   else
   {
      readarraynum--;
      num=readarray[readarraynum];
      showmessage(num);
      addreadarray(num);
      addbackarray(num);
   }
}

void kom_nextmessage(char *arg,char *data)
{
   long num;

   num=nexttext();

   if(num == 0)
   {
      printf(strings[STR_NOMORETEXTS]);
   }
   else
   {
      showmessage(num);
      addreadarray(num);
      addbackarray(num);
   }
}

void kom_backwards(char *arg,char *data)
{
   if(backpos == 1 || backpos == 0)
   {
      printf(strings[STR_NOTBACKWARD]);
   }
   else
   {
      backpos--;
      showmessage(backarray[backpos-1]);
   }
}

void kom_forwards(char *arg,char *data)
{
   if(backpos == backarraynum)
   {
      printf(strings[STR_NOTFORWARD]);
   }
   else
   {
      showmessage(backarray[backpos]);
      backpos++;
   }
}

void kom_readparent(char *arg,char *data)
{
   if(lastread == 0)
   {
      printf(strings[STR_NOTREADTEXTS]);
   }
   else
   {
      long res,chainup;

      res=UMSReadMsgTags(login,UMSTAG_RMsgNum,   lastread,
                               UMSTAG_RChainUp,  &chainup,
                               TAG_DONE);

      if(!res)
      {
         printf(strings[STR_TEXTNRNOTEXIST],lastread);
         return;
      }
      else
      {
         UMSFreeMsg(login,lastread);

         if(chainup)
         {
            showmessage(chainup);
            addbackarray(chainup);
         }
         else
         {
            printf(strings[STR_TEXTNOCOMMENT]);
         }
      }
   }
}

void kom_readagain(char *arg,char *data)
{
   showmessage(lastread);
}

void kom_readmessage(char *arg,char *data)
{
   if(!arg)
   {
      printf(strings[STR_NEEDSARG]);
      return;
   }

   if(!isnum(arg))
   {
      printf(strings[STR_NEEDSNUMARG]);
      return;
   }

   showmessage(atol(arg));
   addbackarray(atol(arg));

   readarraynum=0;
   addreadarray(atol(arg));
}

void kom_dumpmessage(char *arg,char *data)
{
   if(!arg)
   {
      printf(strings[STR_NEEDSARG]);
      return;
   }

   if(!isnum(arg))
   {
      printf(strings[STR_NEEDSNUMARG]);
      return;
   }

   showmessageverbose(atol(arg));
}

void kom_nextselected(char *arg,char *data)
{
   long num;

   num=nextselected();

   if(num == 0)
   {
      printf(strings[STR_NOMORESELECTED]);
   }
   else
   {
      showmessage(num);
      addbackarray(num);

      UMSSelectTags(login,UMSTAG_SelMsg,   num,
                          UMSTAG_SelUnset, UMSFLAG_MATCHSEARCH,
                          UMSTAG_SelWriteLocal, TRUE,
                          TAG_DONE);
   }
}

