#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>

#include <exec/types.h>
#include <exec/memory.h>

#include <dlg/user.h>
#include <dlg/msg.h>

#include <link/io.h>

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/dlg.h>

#include <pragmas/dlg.h>


LONG   __saveds __asm LIBAge(register __d0 SHORT, register __d1 SHORT, register __d2 SHORT);
LONG   __saveds __asm LIBWhenEvent(register __a0 char *);
ULONG  __saveds __asm LIBAmigaTime(void);
void   __saveds __asm LIBMDate(register __a0 char *);
void   __saveds __asm LIBSMDate(register __d0 ULONG, register __a0 char *);

char * __saveds __asm LIBDLGBinSearch(register __a0 char *, register __a1 char *, register __d0 USHORT, register __d1 USHORT, register __d2 USHORT);

LONG   __saveds __asm LIBAddStruct(register __a0 char *,  register __a1 char *, register __d0 ULONG, register __d1 USHORT);
LONG   __saveds __asm LIBGetFirstStruct(register __a0 char *, register __a1 char *, register __d0 ULONG);
LONG   __saveds __asm LIBGetStruct(register __a0 char  *, register __a1 char *, register __d0 ULONG, register __d1 USHORT);

LONG   __saveds __asm LIBFileSize(register __a0 char  *, register __a1 ULONG *);
BOOL   __saveds __asm LIBExists(register __a0 char *);

LONG   __saveds __asm LIBGetComputerType(register __d0 SHORT, register __a0 char *);

void   __saveds __asm LIBUpper(register __a0 char *);
void   __saveds __asm LIBUnderScore(register __a0 char *);
void   __saveds __asm LIBDeScore(register __a0 char *);
void   __saveds __asm LIBCapitalize(register __a0 char *);
void   __saveds __asm LIBClr(register __d0 UBYTE);


BOOL                 ParseTrans(char *,char *,USHORT *);
void                 DoScreen(char *,char *,ULONG,struct ScreenEntry *,USHORT);
struct ScreenEntry  *FindTrans(char *,struct ScreenEntry *,USHORT,UBYTE);
LONG                 TestMatch(char *,char *,UBYTE);
char                 convt(char);


struct ScreenEntry {char *str[2];
                   };

/// Translation table
char Trans[81][9]={/*1*/{"A0"},
                   /*2*/{"A1"},
                   /*3*/{"A2"},
                   /*4*/{"A3"},
                   /*5*/{"A4"},
                   /*6*/{"A5"},
                   /*7*/{"A6"},
                   /*8*/{"A7"},
                   /*9*/{"AB"},
                  /*10*/{"ADDRESS"},
                  /*11*/{"AF"},
                  /*12*/{"AGE"},
                  /*13*/{"AI"},
                  /*14*/{"ALIAS"},
                  /*15*/{"ANSI"},
                  /*16*/{"AO"},
                  /*17*/{"AR"},
                  /*18*/{"AU"},
                  /*19*/{"B0"},
                  /*20*/{"B1"},
                  /*21*/{"B2"},
                  /*22*/{"B3"},
                  /*23*/{"B4"},
                  /*24*/{"B5"},
                  /*25*/{"B6"},
                  /*26*/{"B7"},
                  /*27*/{"BAUD"},
                  /*28*/{"BDAY"},
                  /*29*/{"BMONTH"},
                  /*30*/{"BYEAR"},
                  /*31*/{"BYTESDN"},
                  /*32*/{"BYTESUP"},
                  /*33*/{"CALLS"},
                  /*34*/{"CHARSET"},
                  /*35*/{"CITY"},
                  /*36*/{"COMPUTER"},
                  /*37*/{"COUNTRY"},
                  /*38*/{"CREDIT"},
                  /*39*/{"DATE"},
                  /*40*/{"DAYLIMIT"},
                  /*41*/{"DIRLIMIT"},
                  /*42*/{"DLBYTES"},
                  /*43*/{"FILESDN"},
                  /*44*/{"FILESUP"},
                  /*45*/{"FIRST"},
                  /*46*/{"HELPLVL"},
                  /*47*/{"INDENT"},
                  /*48*/{"JOINED"},
                  /*49*/{"LANGUAGE"},
                  /*50*/{"LAST"},
                  /*51*/{"LASTCALL"},
                  /*52*/{"LASTFILE"},
                  /*53*/{"LASTMSG"},
                  /*54*/{"LEVEL"},
                  /*55*/{"MENUSET"},
                  /*56*/{"MOREOFF"},
                  /*57*/{"MSGENTER"},
                  /*58*/{"MSGREAD"},
                  /*59*/{"NAME"},
                  /*60*/{"NETPRIV"},
                  /*61*/{"PASSWD"},
                  /*62*/{"PHONE"},
                  /*63*/{"PORT"},
                  /*64*/{"POSTAL"},
                  /*65*/{"PROTOCOL"},
                  /*66*/{"PROVINCE"},
                  /*67*/{"RATIO"},
                  /*68*/{"RETURN"},
                  /*69*/{"SCLENGTH"},
                  /*70*/{"SCWIDTH"},
                  /*71*/{"SESLIMIT"},
                  /*72*/{"SYSPAGES"},
                  /*73*/{"TLCALL"},
                  /*74*/{"TLTODAY"},
                  /*75*/{"TUTODAY"},
                  /*76*/{"TUTOT"},
                  /*77*/{"UNAME"},
                  /*78*/{"UPROTO"},
                  /*79*/{"UUCP"},
                  /*80*/{"CLS"}
                  };
//-

/// Substitute
BOOL __saveds __asm LIBSubstitute(register __a0 char             *cstr,
                                  register __a1 char             *result,
                                  register __a2 struct USER_DATA *User,
                                  register __a3 struct Ram_File  *Ram,
                                  register __d0 char             *aport)

{char *s;
 char *port = aport;
 ULONG ctime;
 ULONG ttime;
 SHORT temp;
 UBYTE ansi;
 char  tempstring[80];


*result =  0;
 s      = (char *)LIBDLGBinSearch((char *)Trans,cstr,9,9,80);
 if (!s)  return(FALSE);

 ansi = User->Ansi_Flag;

 switch((char)(((LONG)s-(LONG)Trans)/9)+1)
       {case 1:  if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[30m");
                 break;

        case 2:  if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[31m");
                 break;

        case 3:  if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[32m");
                 break;

        case 4:  if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[33m");
                 break;

        case 5:  if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[34m");
                 break;

        case 6:  if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[35m");
                 break;

        case 7:  if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[36m");
                 break;

        case 8:  if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[37m");
                 break;

        case 9:  if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[1m");
                 break;

        case 10: strcpy(result,User->Address);
                 break;

        case 11: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[5m");
                 break;

        case 12: ASPrintf(NULL,result,"%ld",LIBAge(User->Birth_Year,User->Birth_Month-1,User->Birth_Day));
                 break;

        case 13: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[3m");
                 break;

        case 14: strcpy(result,User->Alias);
                 break;

        case 15: if (ansi & ANSI_COLOR)
                     strcpy(result, "Color");
                   else
                     strcpy(result, "Mono");
                 break;

        case 16: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[0m");
                 break;

        case 17: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[7m");
                 break;

        case 18: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[4m");
                 break;

        case 19: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[40m");
                 break;

        case 20: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[41m");
                 break;

        case 21: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[42m");
                 break;

        case 22: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[43m");
                 break;

        case 23: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[44m");
                 break;

        case 24: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[45m");
                 break;

        case 25: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[46m");
                 break;

        case 26: if (ansi & ANSI_COLOR)
                     strcpy(result, "\033[47m");
                 break;

        case 27: ASPrintf(NULL,result,"%ld",Ram->Baud_Rate);
                 break;

        case 28: ASPrintf(NULL,result,"%ld",User->Birth_Day);
                 break;

        case 29: ASPrintf(NULL,result,"%ld",User->Birth_Month);
                 break;

        case 30: ASPrintf(NULL,result,"%ld",User->Birth_Year);
                 break;

        case 31: ASPrintf(NULL,result,"%ld",User->Bytes_Downloaded);
                 break;

        case 32: ASPrintf(NULL,result,"%ld",User->Bytes_Uploaded);
                 break;

        case 33: ASPrintf(NULL,result,"%ld",User->Total_Calls);
                 break;

        case 34: ASPrintf(NULL,result,"%ld",User->charset);
                 break;

        case 35: strcpy(result,User->City);
                 break;

        case 36: LIBGetComputerType(User->Computer_Type,result);
                 break;

        case 37: strcpy(result,User->Country);
                 break;

        case 38: ASPrintf(NULL,result,"%ld",User->credit);
                 break;

        case 39: LIBMDate(result);
                 break;

        case 40: ASPrintf(NULL,result,"%ld",User->Daily_Limit);
                 break;

        case 41: ASPrintf(NULL,result,"%ld",User->DirLimit);
                 break;

        case 42: ASPrintf(NULL,result,"%ld",(User->Ratio)?(User->Bytes_Uploaded*(LONG)User->Ratio)-User->Bytes_Downloaded:-1);
                 break;

        case 43: ASPrintf(NULL,result,"%ld",User->Files_Downloaded);
                 break;

        case 44: ASPrintf(NULL,result,"%ld",User->Files_Uploaded);
                 break;

        case 45: for(s = Ram->Name; *s  &&  *s!=' '; s++);
                 ctime = s - Ram->Name;
                 movmem(Ram->Name, result, ctime);
               *(result+ctime) = 0;
                 LIBCapitalize(result);
                 break;

        case 46: switch(User->Help_Level)
                       {case 0: strcpy(result,"Novice");
                                break;

                        case 1: strcpy(result,"Intermediate");
                                break;

                        case 2: strcpy(result,"Expert");
                                break;
                       }
                 break;

        case 47: return(FALSE);
                 break;

        case 48: LIBSMDate(User->DateJoined,result);
                 break;

        case 49: strcpy(result,"Not Implemented");
                 break;

        case 50: for(s = Ram->Name+strlen(Ram->Name); (s!=Ram->Name) && (*s!=' '); s--);
                 if (s != Ram->Name)  s++;
                 strcpy(result, s);
                 LIBCapitalize(result);
                 break;

        case 51: strcpy(result,User->Last_Login);
                 break;

        case 52: ASPrintf(NULL,result,"%ld",User->Last_File_Area);
                 break;

        case 53: ASPrintf(NULL,result,"%ld",User->Last_Area);
                 break;

        case 54: ASPrintf(NULL,result,"%ld",User->User_Level);
                 break;

        case 55: ASPrintf(NULL,result,"%ld",User->menuset);
                 break;

        case 56: return(FALSE);
                 break;

        case 57: ASPrintf(NULL,result,"%ld",User->Messages_Entered);
                 break;

        case 58: ASPrintf(NULL,result,"%ld",User->Messages_Read);
                 break;

        case 59: strcpy(result,Ram->Name);
                 LIBCapitalize(result);
                 break;
  
        case 60: strcpy(result, "NONE");
                 if (User->NetMail)
                    {if (User->NetMail&2)
                         strcpy(result, "SYSOP");
                       else
                         strcpy(result, "WRITE");
                    }
                 break;

        case 61: strcpy(result,User->Password);
                 break;

        case 62: strcpy(result,User->Phone);
                 break;

        case 63: strcpy(result, port);
                 break;

        case 64: strcpy(result, User->postal);
                 break;

        case 65: ASPrintf(NULL,result,"S:%c R:%c",User->send,User->receive);
                 break;

        case 66: strcpy(result,User->Prov);
                 break;

        case 67: if (User->Ratio==0)
                     strcpy(result,"None");
                   else
                     ASPrintf(NULL,result,"%ld:1",User->Ratio);
                 break;

        case 68: return(FALSE);
                 break;

        case 69: ASPrintf(NULL,result,"%ld",User->Screen_Len);
                 break;

        case 70: ASPrintf(NULL,result,"%ld",User->Screen_Width);
                 break;

        case 71: ASPrintf(NULL,result,"%ld",User->Session_Limit);
                 break;

        case 72: ASPrintf(NULL,result,"%ld",User->Sysop_Pages);
                 break;

        case 73: ASPrintf(NULL,tempstring,"> NIL: DLG:REMOVEUSER %s",port);
                 LIBUpper(tempstring);
                 temp = LIBWhenEvent(tempstring)+2;
                 if (temp==1)
                     ASPrintf(NULL,result,"less than 2");
                   else
                     ASPrintf(NULL,result,"%ld", temp);
                 break;

        case 74: ctime =  LIBAmigaTime();
                 ttime = (ctime / 60) * 60;
                 if (ctime - ttime > 30)  ttime += 60;

                 ASPrintf(NULL, result, "%ld", User->Daily_Limit - (User->Daily_Used + (SHORT)((ttime - User->Long_Date)/60)) - Ram->suspd_adj);
                 break;

        case 75: ctime =  LIBAmigaTime();
                 ttime = (ctime / 60) * 60;
                 if (ctime - ttime > 30)  ttime += 60;

                 ASPrintf(NULL, result, "%ld", User->Daily_Used  + (SHORT)((ttime - User->Long_Date)/60) - Ram->suspd_adj);
                 break;

        case 76: ASPrintf(NULL,result,"%ld",User->Online_Time+1);
                 break;
    
        case 77: strcpy(result,Ram->Name);
                 LIBCapitalize(result);
                 LIBUnderScore(result);
                 break;

        case 78: ASPrintf(NULL,result,"%ld",User->send);
                 break;

        case 79: switch(User->UUCP)
                       {case 0: strcpy(result, "NONE");   break;
                        case 1: strcpy(result, "CLIENT"); break;
                        case 2: strcpy(result, "WRITE");  break;
                       }
                 break;

        case 80: LIBClr(ansi);
                 break;

       }

 return(TRUE);
}
//-

/// TranslateBuffer
LONG __saveds __asm LIBTranslateBuffer(register __a0 char             *inbuffer,
                                       register __a1 char             *outbuffer,
                                       register __d0 ULONG             maxsize,
                                       register __a2 struct USER_DATA *User,
                                       register __a3 struct Ram_File  *Ram,
                                       register __d1 char             *aport)

{char    *port = aport;
 char    *sbuffr;

 BOOL     ptrans;
 LONG     ocounter;
 USHORT   width;

 char     c;
 UBYTE    result[80];
 UBYTE    padded[80];
 UBYTE    cstr  [10];

 for(ocounter = 0, maxsize--; (c = *inbuffer)  &&  ocounter < maxsize;)
    {if (c != '%')
        {*outbuffer++ = c;
         inbuffer++;
         ocounter++;
         continue;
        }

     sbuffr = ++inbuffer;
     width  =     0;
     ptrans = ParseTrans(inbuffer, cstr, &width);

     if (!LIBSubstitute(cstr, result, User, Ram, port))
        {inbuffer    = sbuffr;
        *outbuffer++ = '%';
         ocounter++;
         continue;
        }

     inbuffer += strlen(cstr);
     if (ptrans)
        {width     = (width>79) ? 79:width;
         inbuffer += 2;
         while(*inbuffer >= '0'  &&  *inbuffer <= '9')
               inbuffer++;
        }

     ASPrintf(NULL, padded, "%-*s", width, result);
     for(sbuffr = padded; (c = *sbuffr)  &&  ocounter < maxsize; sbuffr++)
        {*outbuffer++ = c;
         ocounter++;
        }
    }

 *outbuffer = 0;
 return(ocounter);
}
//-

/// ScreenBuffer
BOOL __saveds __asm LIBScreenBuffer(register __a0 char *inbuf,
                                    register __a1 char *outbuf,
                                    register __d0 ULONG maxsize,
                                    register __a2 char *screenfile)

{char               *mem;
 ULONG               msize;

 struct ScreenEntry *entries;
 ULONG               esize;
 USHORT              cnt;
 USHORT              counter;

 char               *ptr;
 BOOL                succ = FALSE;
 LONG                whichstr;
 BPTR                ifh;

 if (LIBFileSize(screenfile, &msize))          return(succ);
 if (!(ifh = Open(screenfile, MODE_OLDFILE)))  return(succ);

 mem = AllocMem(msize,  MEMF_PUBLIC);
 if (!mem)
    {Close(ifh);
     return(succ);
    }

 Read(ifh, &counter, 2);
 Read(ifh,  mem,     msize-2);
 Close(ifh);

 esize   = counter * sizeof(struct ScreenEntry);
 entries = AllocMem(esize, MEMF_PUBLIC);
 if (entries)
    {succ = TRUE;
     ptr  = mem;
     for(cnt = 0; cnt < counter; cnt++)
         for(whichstr = 0; whichstr < 2; whichstr++)
            {entries[cnt].str[whichstr] = ptr;
             for(;*ptr;ptr++);
             ptr++;
            }

     DoScreen(inbuf, outbuf, maxsize, entries, counter);
     FreeMem(entries, esize);
    }

 FreeMem(mem, msize);
 return(succ);
}
//-

/// ScreenMsg
BOOL __saveds __asm LIBScreenMsg(register __a0 char  *filename,
                                 register __a1 char  *headerfile,
                                 register __d0 UBYTE  msgtype,
                                 register __d1 USHORT area)
{ULONG size;
 char *inbuffer;
 char *outbuffer;
 char  screenfile[60];
 char  checkname [60];
 char  tempstring[72];
 struct Msg_Header header;
 BPTR ifh;

 if (LIBFileSize(filename, &size)==-1)  return(FALSE);

 ASPrintf(NULL,screenfile,"DLGConfig:Misc/Screen.dat");
 switch(msgtype)
       {case 1:
        case 4: ASPrintf(NULL, checkname, "MSG:%ld/Screen.dat", area);
                if (LIBExists(checkname))  strcpy(screenfile, checkname);
                break;

        case 7: ASPrintf(NULL, checkname, "FILE:%ld/Screen.dat", area);
                if (LIBExists(checkname))  strcpy(screenfile, checkname);
                break;
       }

 if (!LIBExists(screenfile)) return(FALSE);

 if (!(inbuffer  = AllocMem(size+1, MEMF_PUBLIC)))
       return(FALSE);

 if (!(ifh = Open(filename, MODE_OLDFILE)))
    {FreeMem(inbuffer, size+1);
     return(FALSE);
    }

 Read(ifh, inbuffer, size);
 Close(ifh);
 inbuffer[size] = 0;

 if (!(outbuffer = AllocMem(size*2, MEMF_PUBLIC)))
    {FreeMem(inbuffer, size+1);
     return(FALSE);
    }

 LIBScreenBuffer(inbuffer,outbuffer,size*2,screenfile);
 DeleteFile(filename);

 if (!(ifh = Open(filename, MODE_NEWFILE)))
    {FreeMem(outbuffer, size*2);
     FreeMem(inbuffer,  size+1);
     return(FALSE);
    }

 Write(ifh, outbuffer, strlen(outbuffer));
 Close(ifh);

 if (msgtype<6 && LIBGetFirstStruct(headerfile,(char *)&header,sizeof(header))!=-1)
    {strcpy(tempstring,header.Title);
     LIBScreenBuffer(tempstring,header.Title,71,screenfile);
     strcpy(tempstring,header.To);
     LIBScreenBuffer(tempstring,header.To,35,screenfile);
     strcpy(tempstring,header.From);
     LIBScreenBuffer(tempstring,header.From,35,screenfile);
     DeleteFile(headerfile);
     LIBAddStruct(headerfile,(char *)&header,sizeof(header),1);
    }

 FreeMem(outbuffer, size*2);
 FreeMem(inbuffer,  size+1);
 return(TRUE);
}
//-

/// ParseTrans
BOOL ParseTrans(char *buf, char *cstr, USHORT *width)

{long count;
 char c = *(buf+1);

 if ((*buf == 'a'              &&
     ((c >='0'  &&  c <= '9')  ||
      (c == 'b'                ||
       c == 'f'                ||
       c == 'i'                ||
       c == 'o'                ||
       c == 'r'                ||
       c == 'u')))             ||
      (*buf == 'b'             &&
      (c >='0'  &&  c <= '9'))
    )
    {*cstr++ = *buf++;
     *cstr++ = *buf;
     *cstr   =   0;
      return(FALSE);
    }

 for(count=0; (count<8) && isalpha(*buf); *cstr++ = *buf++, count++);
 *cstr = 0;

 if (*buf == '.')
    {buf++;
     if (*buf >= '0'  &&  *buf <= '9')
          if (sscanf(buf, "%hd", width))  return(TRUE);
    }

 return(FALSE);
}
//-

/// FindTrans
struct ScreenEntry *FindTrans(char *source,struct ScreenEntry *entries,USHORT numentries,UBYTE fst)

{int index, high, low, cmpres;
 struct ScreenEntry *entry;

 low  = 0;
 high = numentries-1;

 while(low < high)
      {index = (low + high)/2;

       entry =  entries+index;

       cmpres = TestMatch(source,entry->str[0],fst);
       if (cmpres<0)
           high = index;
          else
           if (cmpres > 0)
               low = index + 1;
             else
               high=low=index;
      }

 index  = (low + high)/2;
 entry  =  entries+index;
 cmpres =  TestMatch(source,entry->str[0],fst);

 if (!cmpres)
      return(entry);
    else
      return(NULL);
}
//-

/// DoScreen
void DoScreen(char *inbuf,char *outbuf,ULONG maxsize,struct ScreenEntry *entries,USHORT numentries)

{char               *ptr;
 struct ScreenEntry *entry;
 ULONG               outcount;
 ULONG               len;

 for(ptr=inbuf,outcount=0;*ptr&&(outcount<maxsize);)
    {entry = FindTrans(ptr,entries,numentries,ptr==inbuf);
     if ((ptr==inbuf) && !entry) entry = FindTrans(ptr,entries,numentries,0);

     if (entry)
        {char *src, *dest, *first, *last;
 
         if ((ptr==inbuf)&&!isalnum(*(entry->str[0])))
            {src  = entry->str[0]+1;
             dest = entry->str[1]+1;
            }
          else
            {src  = entry->str[0];
             dest = entry->str[1];
            }

         first =  ptr;
         last  =  ptr+strlen(src)-1;
         len   =  strlen(dest);
         len   = (len>(maxsize-outcount)) ? (maxsize-outcount) : len;

         if (!isalpha(*first))
            {len--;
             outbuf[outcount++]=*first++;
             movmem(dest+1,outbuf+outcount,len);
            }
          else
             movmem(dest,outbuf+outcount,len);

         if (isupper(*first))
             outbuf[outcount]=toupper(outbuf[outcount]);
           else
             outbuf[outcount]=tolower(outbuf[outcount]);

         outcount+=len;
         if (!isalpha(*last))
            {outcount--;
             ptr--;
            }

         ptr+=strlen(src);
        }
      else
        outbuf[outcount++]=*ptr++;
    }

 outbuf[outcount]='\0';
}
//-

/// TestMatch
LONG TestMatch(char *str1,char *str2,UBYTE fst)

{UBYTE word1 = FALSE;
 UBYTE word2 = FALSE;

 if (!isalnum(*str1)) word1=TRUE;
 if (!isalnum(*str2)) word2=TRUE;

 if (fst)
     if (!isalnum(*str2)) str2++;
    else
    return(1);

 for(;*str1 && *str2;str1++,str2++)
      if (convt(*str1)!=convt(*str2)) break;

 if (!*str2) return(0); 

 if (!isalnum(*str1) && isalnum(*str2) && !word1 && !word2) return(-1);

 return(convt(*str1)-convt(*str2));
}
//-

/// convt
char convt(char c)

{if (isalnum(c))  return((char)toupper(c));
 return('|');
}
//-

