//  This may look like C code, but it is really -*- C++ -*-

//  ------------------------------------------------------------------
//  The Goldware Library
//  Copyright (C) 1990-1999 Odinn Sorensen
//  ------------------------------------------------------------------
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Library General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Library General Public License for more details.
//
//  You should have received a copy of the GNU Library General Public
//  License along with this program; if not, write to the Free
//  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
//  MA 02111-1307, USA
//  ------------------------------------------------------------------
//  $Id$
//  ------------------------------------------------------------------
//  Fido/Opus/FTSC (*.MSG) type handling
//  ------------------------------------------------------------------

#include <gdbgtrk.h>
#include <gmemall.h>
#include <gstrall.h>
#include <gmoprot.h>
#include <gmofido.h>


//  ------------------------------------------------------------------

char* FidoArea::user_lookup(char* __lookfor)
{
    Path userfile;
    strxcpy(userfile, AddPath(fidowide->squishuserpath, "USER.BBS"), sizeof(Path));
    wide->user->gufh = ::sopen(userfile, O_RDONLY|O_BINARY, WideSharemode, S_STDRD);
    wide->user->findwild(__lookfor, __lookfor);
    ::close(wide->user->gufh);

    if(wide->user->found)
        return __lookfor;
    else
        return NULL;
}


//  ------------------------------------------------------------------

int FidoArea::renumber()
{

    GFTRK("FidoRenumber");

    // Save the current lastread
    save_lastread();

    // Rescan the area
    scan();

    // In echo or local, start with 2.MSG so we don't conflict
    // with highwater marks, unless there is already a 1.MSG
    uint _msgno1st = 1;
    if(not isnet() and (Msgn->at(0) != 1))
        _msgno1st++;

    // Renumber *.MSG files
    uint _count = 0;
    uint _msgno = _msgno1st;
    while(_count < Msgn->Count())
    {

        // Only renumber a msg if different
        if(_msgno != Msgn->at(_count))
        {

            Path _oldname, _newname;
            sprintf(_oldname, "%s%u.msg", real_path(), Msgn->at(_count));
            sprintf(_newname, "%s%u.msg", real_path(), _msgno);

            // Get the file attribute of the message
            struct stat st;
            stat(_oldname, &st);
            bool readonly = not (st.st_mode & S_IWUSR);
            if(readonly)
                chmod(_oldname, S_STDRW);

            // Show progress
            char buf[100];
            sprintf(buf,
                    "%s: %u.msg -> %u.msg%s",
                    "Renumbering",
                    Msgn->at(_count),
                    _msgno,
                    readonly ? " (locked)" : ""
                   );
            FidoRenumberProgress(buf);

            // Update the msg
            int _fh = test_open(_oldname, O_RDWR|O_BINARY, SH_DENYWR);
            if(_fh != -1)
            {

                // Read the header
                FidoHdr _hdr;
                read(_fh, &_hdr, sizeof(FidoHdr));

                // Update the replylinks
                if(_hdr.replyto or _hdr.reply1st)
                {
                    _hdr.replyto  = (word)Msgn->ToReln(_hdr.replyto);
                    _hdr.reply1st = (word)Msgn->ToReln(_hdr.reply1st);
                    lseekset(_fh, 0);
                    write(_fh, &_hdr, sizeof(FidoHdr));
                }
                ::close(_fh);

                // Rename the message file
                rename(_oldname, _newname);
                if(readonly)
                    chmod(_oldname, S_STDRD);
            }
        }
        _msgno++;
        _count++;
    }

    // Renumber the personal mail marks
    for(_count=0; _count<PMrk->Tags(); _count++)
        PMrk->at(_count) = Msgn->ToReln(PMrk->at(_count)) + _msgno1st - 1;

    // Renumber the index
    for(_count=0; _count<Msgn->Count(); _count++)
        Msgn->at(_count) = _count + _msgno1st;

    GFTRK(0);

    return true;
}


//  ------------------------------------------------------------------
//  Hexdump the current message header

Line* FidoArea::make_dump_msg(Line*& lin, gmsg* msg, char* lng_head)
{

    GFTRK("FidoMakeDump");

    FidoHdr _hdr;
    load_message(GMSG_HDRTXT, msg, _hdr);

    char buf[100];
    Line* line = lin =
                     AddLine (NULL, "Hexdump of Fido/Opus-style message header and text");
    AddLineF(line, "------------------------------------------------------------------------------");
    line = AddLine(line, "");
    AddLineF(line, "File     : %s%u.msg", real_path(), msg->msgno);
    AddLineF(line, "From     : %-35.35s", _hdr.by);
    AddLineF(line, "To       : %-35.35s", _hdr.to);
    AddLineF(line, "Subject  : %-72.72s", _hdr.re);
    AddLineF(line, "DateTime : %-20.20s", _hdr.datetime);
    if(isopus())
        AddLineF(line, "OrigAddr : %u/%u", _hdr.orignet, _hdr.orignode);
    else
        AddLineF(line, "OrigAddr : %u:%u/%u.%u", _hdr.ftsc.origzone, _hdr.orignet, _hdr.orignode, _hdr.ftsc.origpoint);
    if(isopus())
        AddLineF(line, "DestAddr : %u/%u", _hdr.destnet, _hdr.destnode);
    else
        AddLineF(line, "DestAddr : %u:%u/%u.%u", _hdr.ftsc.destzone, _hdr.destnet, _hdr.destnode, _hdr.ftsc.destpoint);
    AddLineF(line, "Reply    : %u  See : %u", _hdr.replyto, _hdr.reply1st);
    AddLineF(line, "TimesRead: %u  Cost: %u", _hdr.timesread, _hdr.cost);
    AddLineF(line, "Attr     : %u (%04X)", _hdr.attr, _hdr.attr);
    if(isopus())
    {
        AddLineF(line, "Written  : %s (%08Xh)", FTimeToStr(buf, _hdr.opus.written), *(uint*)&_hdr.opus.written);
        AddLineF(line, "Arrived  : %s (%08Xh)", FTimeToStr(buf, _hdr.opus.arrived), *(uint*)&_hdr.opus.arrived);
    }
    AddLineF(line, "UserRecno: %u (%s)", wide->userno, WideUsername[0]);
    line = AddLine(line, "");
    AddLine(line, lng_head);
    line = AddLine(line, "");

    int _count;
    char* _ptr = (char*)&_hdr;
    for(_count=0; _count<190; _ptr+=16,_count+=16)
    {
        sprintf(buf, "%04X   ", _count);
        HexDump16(buf+7, _ptr, 16, HEX_DUMP2);
        line = AddLine(line, buf);
    }
    sprintf(buf, "%04X   ", _count);
    HexDump16(buf+7, _ptr, 14, HEX_DUMP2);
    line = AddLine(line, buf);

    GFTRK(0);

    return line;
}


//  ------------------------------------------------------------------
