text:
#include <stdarg.h>
#include <stdio.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
#include "mshtmcid.h"
#include "shlguid.h"

#include "wine/debug.h"

#include "mshtml_private.h"
#include "resource.h"

WINE_DEFAULT_DEBUG_CHANNEL(mshtml);

#define NSCMD_ALIGN        "cmd_align"
#define NSCMD_BEGINLINE    "cmd_beginLine"
#define NSCMD_BOLD         "cmd_bold"
#define NSCMD_CHARNEXT     "cmd_charNext"
#define NSCMD_CHARPREVIOUS "cmd_charPrevious"
#define NSCMD_COPY         "cmd_copy"
#define NSCMD_CUT          "cmd_cut"
#define NSCMD_DELETECHARFORWARD   "cmd_deleteCharForward"
#define NSCMD_DELETEWORDFORWARD   "cmd_deleteWordForward"
#define NSCMD_ENDLINE      "cmd_endLine"
#define NSCMD_FONTCOLOR    "cmd_fontColor"
#define NSCMD_FONTFACE     "cmd_fontFace"
#define NSCMD_INDENT       "cmd_indent"
#define NSCMD_INSERTHR     "cmd_insertHR"
#define NSCMD_INSERTLINKNOUI    "cmd_insertLinkNoUI"
#define NSCMD_ITALIC       "cmd_italic"
#define NSCMD_LINENEXT     "cmd_lineNext"
#define NSCMD_LINEPREVIOUS "cmd_linePrevious"
#define NSCMD_MOVEBOTTOM   "cmd_moveBottom"
#define NSCMD_MOVEPAGEDOWN "cmd_movePageDown"
#define NSCMD_MOVEPAGEUP   "cmd_movePageUp"
#define NSCMD_MOVETOP      "cmd_moveTop"
#define NSCMD_OL           "cmd_ol"
#define NSCMD_OUTDENT      "cmd_outdent"
#define NSCMD_PASTE        "cmd_paste"
#define NSCMD_SELECTALL           "cmd_selectAll"
#define NSCMD_SELECTBEGINLINE     "cmd_selectBeginLine"
#define NSCMD_SELECTBOTTOM        "cmd_selectBottom"
#define NSCMD_SELECTCHARNEXT      "cmd_selectCharNext"
#define NSCMD_SELECTCHARPREVIOUS  "cmd_selectCharPrevious"
#define NSCMD_SELECTENDLINE       "cmd_selectEndLine"
#define NSCMD_SELECTLINENEXT      "cmd_selectLineNext"
#define NSCMD_SELECTLINEPREVIOUS  "cmd_selectLinePrevious"
#define NSCMD_SELECTPAGEDOWN      "cmd_selectPageDown"
#define NSCMD_SELECTPAGEUP        "cmd_selectPageUp"
#define NSCMD_SELECTTOP           "cmd_selectTop"
#define NSCMD_SELECTWORDNEXT      "cmd_selectWordNext"
#define NSCMD_SELECTWORDPREVIOUS  "cmd_selectWordPrevious"
#define NSCMD_UL           "cmd_ul"
#define NSCMD_UNDERLINE    "cmd_underline"
#define NSCMD_WORDNEXT     "cmd_wordNext"
#define NSCMD_WORDPREVIOUS "cmd_wordPrevious"

#define NSSTATE_ATTRIBUTE "state_attribute"
#define NSSTATE_ALL       "state_all"

#define NSALIGN_CENTER "center"
#define NSALIGN_LEFT   "left"
#define NSALIGN_RIGHT  "right"

#define DOM_VK_LEFT     VK_LEFT
#define DOM_VK_UP       VK_UP
#define DOM_VK_RIGHT    VK_RIGHT
#define DOM_VK_DOWN     VK_DOWN
#define DOM_VK_DELETE   VK_DELETE
#define DOM_VK_HOME     VK_HOME
#define DOM_VK_END      VK_END

static const WCHAR fontW[] = {'f','o','n','t',0};
static const WCHAR sizeW[] = {'s','i','z','e',0};

void set_dirty(HTMLDocument *This, VARIANT_BOOL dirty)
{
    nsresult nsres;

    if(This->doc_obj->usermode != EDITMODE || !This->doc_obj->nscontainer || !This->doc_obj->nscontainer->editor)
        return;

    if(dirty) {
        nsres = nsIEditor_IncrementModificationCount(This->doc_obj->nscontainer->editor, 1);
        if(NS_FAILED(nsres))
            ERR("IncrementModificationCount failed: %08x\n", nsres);
    }else {
        nsres = nsIEditor_ResetModificationCount(This->doc_obj->nscontainer->editor);
        if(NS_FAILED(nsres))
            ERR("ResetModificationCount failed: %08x\n", nsres);
    }
}

static void do_ns_editor_command(NSContainer *This, const char *cmd)
{
    nsresult nsres;

    if(!This->editor_controller)
        return;

    nsres = nsIController_DoCommand(This->editor_controller, cmd);
    if(NS_FAILED(nsres))
        ERR("DoCommand(%s) failed: %08x\n", debugstr_a(cmd), nsres);
}

static nsresult get_ns_command_state(NSContainer *This, const char *cmd, nsICommandParams *nsparam)
{
    nsICommandManager *cmdmgr;
    nsresult nsres;

    nsres = get_nsinterface((nsISupports*)This->webbrowser, &IID_nsICommandManager, (void**)&cmdmgr);
    if(NS_FAILED(nsres)) {
        ERR("Could not get nsICommandManager: %08x\n", nsres);
        return nsres;
    }

    nsres = nsICommandManager_GetCommandState(cmdmgr, cmd, This->doc->basedoc.window->nswindow, nsparam);
    if(NS_FAILED(nsres))
        ERR("GetCommandState(%s) failed: %08x\n", debugstr_a(cmd), nsres);

    nsICommandManager_Release(cmdmgr);
    return nsres;
}

static DWORD query_ns_edit_status(HTMLDocument *This, const char *nscmd)
{
    nsICommandParams *nsparam;
    cpp_bool b = FALSE;

    if(This->doc_obj->usermode != EDITMODE || This->window->readystate < READYSTATE_INTERACTIVE)
        return OLECMDF_SUPPORTED;

    if(This->doc_obj->nscontainer && nscmd) {
        nsparam = create_nscommand_params();
        get_ns_command_state(This->doc_obj->nscontainer, nscmd, nsparam);

        nsICommandParams_GetBooleanValue(nsparam, NSSTATE_ALL, &b);

        nsICommandParams_Release(nsparam);
    }

    return OLECMDF_SUPPORTED | OLECMDF_ENABLED | (b ? OLECMDF_LATCHED : 0);
}

static void set_ns_align(HTMLDocument *This, const char *align_str)
{
    nsICommandParams *nsparam;

    if(!This->doc_obj->nscontainer)
        return;

    nsparam = create_nscommand_params();
    nsICommandParams_SetCStringValue(nsparam, NSSTATE_ATTRIBUTE, align_str);

    do_ns_command(This, NSCMD_ALIGN, nsparam);

    nsICommandParams_Release(nsparam);
}

static DWORD query_align_status(HTMLDocument *This, const WCHAR *align)
{
    DWORD ret = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
    nsAString justify_str;
    cpp_bool b;
    nsresult nsres;

    if(This->doc_obj->usermode != EDITMODE || This->window->readystate < READYSTATE_INTERACTIVE)
        return OLECMDF_SUPPORTED;

    nsAString_Init(&justify_str, align);
    nsres = nsIDOMHTMLDocument_QueryCommandState(This->doc_node->nsdoc, &justify_str, &b);
    nsAString_Finish(&justify_str);
    if(NS_SUCCEEDED(nsres) && b)
        ret |= OLECMDF_LATCHED;

    return ret;
}

static nsISelection *get_ns_selection(HTMLDocument *This)
{
    nsISelection *nsselection = NULL;
    nsresult nsres;

    nsres = nsIDOMWindow_GetSelection(This->window->nswindow, &nsselection);
    if(NS_FAILED(nsres))
        ERR("GetSelection failed %08x\n", nsres);

    return nsselection;

}

static void remove_child_attr(nsIDOMElement *elem, LPCWSTR tag, nsAString *attr_str)
{
    cpp_bool has_children;
    UINT32 child_cnt, i;
    nsIDOMNode *child_node;
    nsIDOMNodeList *node_list;
    UINT16 node_type;

    nsIDOMElement_HasChildNodes(elem, &has_children);
    if(!has_children)
        return;

    nsIDOMElement_GetChildNodes(elem, &node_list);
    nsIDOMNodeList_GetLength(node_list, &child_cnt);

    for(i=0; i<child_cnt; i++) {
        nsIDOMNodeList_Item(node_list, i, &child_node);

        nsIDOMNode_GetNodeType(child_node, &node_type);
        if(node_type == ELEMENT_NODE) {
            nsIDOMElement *child_elem;
            nsAString tag_str;
            const PRUnichar *ctag;

            nsIDOMNode_QueryInterface(child_node, &IID_nsIDOMElement, (void**)&child_elem);

            nsAString_Init(&tag_str, NULL);
            nsIDOMElement_GetTagName(child_elem, &tag_str);
            nsAString_GetData(&tag_str, &ctag);

            if(!strcmpiW(ctag, tag))
                /* FIXME: remove node if there are no more attributes */
                nsIDOMElement_RemoveAttribute(child_elem, attr_str);

            nsAString_Finish(&tag_str);

            remove_child_attr(child_elem, tag, attr_str);

            nsIDOMElement_Release(child_elem);
        }

        nsIDOMNode_Release(child_node);
    }

    nsIDOMNodeList_Release(node_list);
}

static void get_font_size(HTMLDocument *This, WCHAR *ret)
{
    nsISelection *nsselection = get_ns_selection(This);
    nsIDOMElement *elem = NULL;
    nsIDOMNode *node = NULL, *tmp_node;
    nsAString tag_str;
    LPCWSTR tag;
    UINT16 node_type;
    nsresult nsres;

    *ret = 0;

    if(!nsselection)
        return;

    nsISelection_GetFocusNode(nsselection, &node);
    nsISelection_Release(nsselection);

    while(node) {
        nsres = nsIDOMNode_GetNodeType(node, &node_type);
        if(NS_FAILED(nsres) || node_type == DOCUMENT_NODE)
            break;

        if(node_type == ELEMENT_NODE) {
            nsIDOMNode_QueryInterface(node, &IID_nsIDOMElement, (void**)&elem);

            nsAString_Init(&tag_str, NULL);
            nsIDOMElement_GetTagName(elem, &tag_str);
            nsAString_GetData(&tag_str, &tag);

            if(!strcmpiW(tag, fontW)) {
                nsAString size_str, val_str;
                LPCWSTR val;

                TRACE("found font tag %p\n", elem);

                nsAString_InitDepend(&size_str, sizeW);
                nsAString_Init(&val_str, NULL);

                nsIDOMElement_GetAttribute(elem, &size_str, &val_str);
                nsAString_GetData(&val_str, &val);

                if(*val) {
                    TRACE("found size %s\n", debugstr_w(val));
                    strcpyW(ret, val);
                }

                nsAString_Finish(&size_str);
                nsAString_Finish(&val_str);
            }

            nsAString_Finish(&tag_str);

            nsIDOMElement_Release(elem);
        }

        if(*ret)
            break;

        tmp_node = node;
        nsIDOMNode_GetParentNode(node, &node);
        nsIDOMNode_Release(tmp_node);
    }

    if(node)
        nsIDOMNode_Release(node);
}

static void set_font_size(HTMLDocument *This, LPCWSTR size)
{
    nsISelection *nsselection;
    cpp_bool collapsed;
    nsIDOMHTMLElement *elem;
    nsIDOMRange *range;
    LONG range_cnt = 0;
    nsAString size_str;
    nsAString val_str;

    if(!This->doc_node->nsdoc) {
        WARN("NULL nsdoc\n");
        return;
    }

    nsselection = get_ns_selection(This);
    if(!nsselection)
        return;

    nsISelection_GetRangeCount(nsselection, &range_cnt);
    if(range_cnt != 1) {
        FIXME("range_cnt %d not supprted\n", range_cnt);
        if(!range_cnt) {
            nsISelection_Release(nsselection);
            return;
        }
    }

    create_nselem(This->doc_node, fontW, &elem);

    nsAString_InitDepend(&size_str, sizeW);
    nsAString_InitDepend(&val_str, size);

    nsIDOMHTMLElement_SetAttribute(elem, &size_str, &val_str);
    nsAString_Finish(&val_str);

    nsISelection_GetRangeAt(nsselection, 0, &range);
    nsISelection_GetIsCollapsed(nsselection, &collapsed);
    nsISelection_RemoveAllRanges(nsselection);

    nsIDOMRange_SurroundContents(range, (nsIDOMNode*)elem);

    if(collapsed) {
        nsISelection_Collapse(nsselection, (nsIDOMNode*)elem, 0);
    }else {
        /* Remove all size attributes from the range */
        remove_child_attr((nsIDOMElement*)elem, fontW, &size_str);
        nsISelection_SelectAllChildren(nsselection, (nsIDOMNode*)elem);
    }

    nsISelection_Release(nsselection);
    nsIDOMRange_Release(range);
    nsIDOMHTMLElement_Release(elem);

    nsAString_Finish(&size_str);

    set_dirty(This, VARIANT_TRUE);
}

static void handle_arrow_key(HTMLDocument *This, nsIDOMKeyEvent *event, const char * const cmds[4])
{
    int i=0;
    cpp_bool b;

    nsIDOMKeyEvent_GetCtrlKey(event, &b);
    if(b)
        i |= 1;

    nsIDOMKeyEvent_GetShiftKey(event, &b);
    if(b)
        i |= 2;

    if(cmds[i])
        do_ns_editor_command(This->doc_obj->nscontainer, cmds[i]);

    nsIDOMKeyEvent_PreventDefault(event);
}

void handle_edit_event(HTMLDocument *This, nsIDOMEvent *event)
{
    nsIDOMKeyEvent *key_event;
    UINT32 code;

    nsIDOMEvent_QueryInterface(event, &IID_nsIDOMKeyEvent, (void**)&key_event);

    nsIDOMKeyEvent_GetKeyCode(key_event, &code);

    switch(code) {
    case DOM_VK_LEFT: {
        static const char * const cmds[] = {
            NSCMD_CHARPREVIOUS,
            NSCMD_WORDPREVIOUS,
            NSCMD_SELECTCHARPREVIOUS,
            NSCMD_SELECTWORDPREVIOUS
        };

        TRACE("left\n");
        handle_arrow_key(This, key_event, cmds);
        break;
    }
    case DOM_VK_RIGHT: {
        static const char * const cmds[] = {
            NSCMD_CHARNEXT,
            NSCMD_WORDNEXT,
            NSCMD_SELECTCHARNEXT,
            NSCMD_SELECTWORDNEXT
        };

        TRACE("right\n");
        handle_arrow_key(This, key_event, cmds);
        break;
    }
    case DOM_VK_UP: {
        static const char * const cmds[] = {
            NSCMD_LINEPREVIOUS,
            NSCMD_MOVEPAGEUP,
            NSCMD_SELECTLINEPREVIOUS,
            NSCMD_SELECTPAGEUP
        };

        TRACE("up\n");
        handle_arrow_key(This, key_event, cmds);
        break;
    }
    case DOM_VK_DOWN: {
        static const char * const cmds[] = {
            NSCMD_LINENEXT,
            NSCMD_MOVEPAGEDOWN,
            NSCMD_SELECTLINENEXT,
            NSCMD_SELECTPAGEDOWN
        };

        TRACE("down\n");
        handle_arrow_key(This, key_event, cmds);
        break;
    }
    case DOM_VK_DELETE: {
        static const char * const cmds[] = {
            NSCMD_DELETECHARFORWARD,
            NSCMD_DELETEWORDFORWARD,
            NULL, NULL
        };

        TRACE("delete\n");
        handle_arrow_key(This, key_event, cmds);
        break;
    }
    case DOM_VK_HOME: {
        static const char * const cmds[] = {
            NSCMD_BEGINLINE,
            NSCMD_MOVETOP,
            NSCMD_SELECTBEGINLINE,
            NSCMD_SELECTTOP
        };

        TRACE("home\n");
        handle_arrow_key(This, key_event, cmds);
        break;
    }
    case DOM_VK_END: {
        static const char * const cmds[] = {
            NSCMD_ENDLINE,
            NSCMD_MOVEBOTTOM,
            NSCMD_SELECTENDLINE,
            NSCMD_SELECTBOTTOM
        };

        TRACE("end\n");
        handle_arrow_key(This, key_event, cmds);
        break;
    }
    }

    nsIDOMKeyEvent_Release(key_event);
}

void handle_edit_load(HTMLDocument *This)
{
    get_editor_controller(This->doc_obj->nscontainer);
}

static void set_ns_fontname(HTMLDocument *This, const char *fontname)
{
    nsICommandParams *nsparam = create_nscommand_params();

    nsICommandParams_SetCStringValue(nsparam, NSSTATE_ATTRIBUTE, fontname);
    do_ns_command(This, NSCMD_FONTFACE, nsparam);
    nsICommandParams_Release(nsparam);
}

static HRESULT exec_delete(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)->(%p %p)\n", This, in, out);

    if(This->doc_obj->nscontainer)
        do_ns_editor_command(This->doc_obj->nscontainer, NSCMD_DELETECHARFORWARD);

    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_fontname(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)->(%p %p)\n", This, in, out);

    if(!This->doc_obj->nscontainer) {
        update_doc(This, UPDATE_UI);
        return E_FAIL;
    }

    if(in) {
        char *stra;

        if(V_VT(in) != VT_BSTR) {
            FIXME("Unsupported fontname %s\n", debugstr_variant(out));
            return E_INVALIDARG;
        }

        TRACE("%s\n", debugstr_w(V_BSTR(in)));

        stra = heap_strdupWtoA(V_BSTR(in));
        set_ns_fontname(This, stra);
        heap_free(stra);

        update_doc(This, UPDATE_UI);
    }

    if(out) {
        nsICommandParams *nsparam;
        LPWSTR strw;
        char *stra;
        DWORD len;
        nsresult nsres;

        V_VT(out) = VT_BSTR;
        V_BSTR(out) = NULL;

        nsparam = create_nscommand_params();

        nsres = get_ns_command_state(This->doc_obj->nscontainer, NSCMD_FONTFACE, nsparam);
        if(NS_FAILED(nsres))
            return S_OK;

        nsICommandParams_GetCStringValue(nsparam, NSSTATE_ATTRIBUTE, &stra);
        nsICommandParams_Release(nsparam);

        len = MultiByteToWideChar(CP_ACP, 0, stra, -1, NULL, 0);
        strw = heap_alloc(len*sizeof(WCHAR));
        MultiByteToWideChar(CP_ACP, 0, stra, -1, strw, len);
        nsfree(stra);

        V_BSTR(out) = SysAllocString(strw);
        heap_free(strw);
    }

    return S_OK;
}

static HRESULT exec_forecolor(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)->(%p %p)\n", This, in, out);

    if(in) {
        if(V_VT(in) == VT_I4) {
            nsICommandParams *nsparam = create_nscommand_params();
            char color_str[10];

            sprintf(color_str, "#%02x%02x%02x",
                    V_I4(in)&0xff, (V_I4(in)>>8)&0xff, (V_I4(in)>>16)&0xff);

            nsICommandParams_SetCStringValue(nsparam, NSSTATE_ATTRIBUTE, color_str);
            do_ns_command(This, NSCMD_FONTCOLOR, nsparam);

            nsICommandParams_Release(nsparam);
        }else {
            FIXME("unsupported forecolor %s\n", debugstr_variant(in));
        }

        update_doc(This, UPDATE_UI);
    }

    if(out) {
        FIXME("unsupported out\n");
        return E_NOTIMPL;
    }

    return S_OK;
}

static HRESULT exec_fontsize(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)->(%p %p)\n", This, in, out);

    if(out) {
        WCHAR val[10] = {0};

        get_font_size(This, val);
        V_VT(out) = VT_I4;
        V_I4(out) = strtolW(val, NULL, 10);
    }

    if(in) {
        switch(V_VT(in)) {
        case VT_I4: {
            WCHAR size[10];
            static const WCHAR format[] = {'%','d',0};
            wsprintfW(size, format, V_I4(in));
            set_font_size(This, size);
            break;
        }
        case VT_BSTR:
            set_font_size(This, V_BSTR(in));
            break;
        default:
            FIXME("unsupported fontsize %s\n", debugstr_variant(in));
        }

        update_doc(This, UPDATE_UI);
    }

    return S_OK;
}

static HRESULT exec_font(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{

    FIXME("(%p)->(%p %p)\n", This, in, out);
    return E_NOTIMPL;
}

static HRESULT exec_selectall(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    if(This->doc_obj->nscontainer)
        do_ns_command(This, NSCMD_SELECTALL, NULL);

    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_bold(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    if(This->doc_obj->nscontainer)
        do_ns_command(This, NSCMD_BOLD, NULL);

    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_italic(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    if(This->doc_obj->nscontainer)
        do_ns_command(This, NSCMD_ITALIC, NULL);

    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT query_justify(HTMLDocument *This, OLECMD *cmd)
{
    static const PRUnichar justifycenterW[] = {'j','u','s','t','i','f','y','c','e','n','t','e','r',0};
    static const PRUnichar justifyrightW[] = {'j','u','s','t','i','f','y','r','i','g','h','t',0};

    switch(cmd->cmdID) {
    case IDM_JUSTIFYCENTER:
        TRACE("(%p) IDM_JUSTIFYCENTER\n", This);
        cmd->cmdf = query_align_status(This, justifycenterW);
        break;
    case IDM_JUSTIFYLEFT:
        TRACE("(%p) IDM_JUSTIFYLEFT\n", This);
        /* FIXME: We should set OLECMDF_LATCHED only if it's set explicitly. */
        if(This->doc_obj->usermode != EDITMODE || This->window->readystate < READYSTATE_INTERACTIVE)
            cmd->cmdf = OLECMDF_SUPPORTED;
        else
            cmd->cmdf = OLECMDF_SUPPORTED | OLECMDF_ENABLED;
        break;
    case IDM_JUSTIFYRIGHT:
        TRACE("(%p) IDM_JUSTIFYRIGHT\n", This);
        cmd->cmdf = query_align_status(This, justifyrightW);
        break;
    }

    return S_OK;
}

static HRESULT exec_justifycenter(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    set_ns_align(This, NSALIGN_CENTER);
    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_justifyleft(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    set_ns_align(This, NSALIGN_LEFT);
    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_justifyright(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    set_ns_align(This, NSALIGN_RIGHT);
    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_underline(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    do_ns_command(This, NSCMD_UNDERLINE, NULL);
    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_horizontalline(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    do_ns_command(This, NSCMD_INSERTHR, NULL);
    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_orderlist(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    do_ns_command(This, NSCMD_OL, NULL);
    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_unorderlist(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    do_ns_command(This, NSCMD_UL, NULL);
    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_indent(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    do_ns_command(This, NSCMD_INDENT, NULL);
    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_outdent(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)\n", This);

    if(in || out)
        FIXME("unsupported args\n");

    do_ns_command(This, NSCMD_OUTDENT, NULL);
    update_doc(This, UPDATE_UI);
    return S_OK;
}

static HRESULT exec_composesettings(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    WCHAR *ptr;

    if(out || !in || V_VT(in) != VT_BSTR) {
        WARN("invalid arg %s\n", debugstr_variant(in));
        return E_INVALIDARG;
    }

    TRACE("(%p)->(%x %s)\n", This, cmdexecopt, debugstr_w(V_BSTR(in)));

    update_doc(This, UPDATE_UI);

    ptr = V_BSTR(in);
    if(*ptr == '1')
        exec_bold(This, cmdexecopt, NULL, NULL);
    ptr = strchrW(ptr, ',');
    if(!ptr)
        return S_OK;

    if(*++ptr == '1')
        exec_italic(This, cmdexecopt, NULL, NULL);
    ptr = strchrW(ptr, ',');
    if(!ptr)
        return S_OK;

    if(*++ptr == '1')
        exec_underline(This, cmdexecopt, NULL, NULL);
    ptr = strchrW(ptr, ',');
    if(!ptr)
        return S_OK;

    if(isdigitW(*++ptr)) {
        VARIANT v;

        V_VT(&v) = VT_I4;
        V_I4(&v) = *ptr-'0';

        exec_fontsize(This, cmdexecopt, &v, NULL);
    }
    ptr = strchrW(ptr, ',');
    if(!ptr)
        return S_OK;

    if(*++ptr != ',')
        FIXME("set font color\n");
    ptr = strchrW(ptr, ',');
    if(!ptr)
        return S_OK;

    if(*++ptr != ',')
        FIXME("set background color\n");
    ptr = strchrW(ptr, ',');
    if(!ptr)
        return S_OK;

    ptr++;
    if(*ptr) {
        VARIANT v;

        V_VT(&v) = VT_BSTR;
        V_BSTR(&v) = SysAllocString(ptr);

        exec_fontname(This, cmdexecopt, &v, NULL);

        SysFreeString(V_BSTR(&v));
    }

    return S_OK;
}

HRESULT editor_exec_copy(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    update_doc(This, UPDATE_UI);

    if(!This->doc_obj->nscontainer)
        return E_FAIL;

    do_ns_editor_command(This->doc_obj->nscontainer, NSCMD_COPY);
    return S_OK;
}

HRESULT editor_exec_cut(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    update_doc(This, UPDATE_UI);

    if(!This->doc_obj->nscontainer)
        return E_FAIL;

    do_ns_editor_command(This->doc_obj->nscontainer, NSCMD_CUT);
    return S_OK;
}

HRESULT editor_exec_paste(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    update_doc(This, UPDATE_UI);

    if(!This->doc_obj->nscontainer)
        return E_FAIL;

    do_ns_editor_command(This->doc_obj->nscontainer, NSCMD_PASTE);
    return S_OK;
}

static HRESULT exec_setdirty(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    TRACE("(%p)->(%08x %p %p)\n", This, cmdexecopt, in, out);

    if(!in)
        return S_OK;

    if(V_VT(in) == VT_BOOL)
        set_dirty(This, V_BOOL(in));
    else
        FIXME("unsupported arg %s\n", debugstr_variant(in));

    return S_OK;
}

static HRESULT query_edit_status(HTMLDocument *This, OLECMD *cmd)
{
    switch(cmd->cmdID) {
    case IDM_DELETE:
        TRACE("CGID_MSHTML: IDM_DELETE\n");
        cmd->cmdf = query_ns_edit_status(This, NULL);
        break;
    case IDM_FONTNAME:
        TRACE("CGID_MSHTML: IDM_FONTNAME\n");
        cmd->cmdf = query_ns_edit_status(This, NULL);
        break;
    case IDM_FONTSIZE:
        TRACE("CGID_MSHTML: IDM_FONTSIZE\n");
        cmd->cmdf = query_ns_edit_status(This, NULL);
        break;
    case IDM_BOLD:
        TRACE("CGID_MSHTML: IDM_BOLD\n");
        cmd->cmdf = query_ns_edit_status(This, NSCMD_BOLD);
        break;
    case IDM_FORECOLOR:
        TRACE("CGID_MSHTML: IDM_FORECOLOR\n");
        cmd->cmdf = query_ns_edit_status(This, NULL);
        break;
    case IDM_ITALIC:
        TRACE("CGID_MSHTML: IDM_ITALIC\n");
        cmd->cmdf = query_ns_edit_status(This, NSCMD_ITALIC);
        break;
    case IDM_UNDERLINE:
        TRACE("CGID_MSHTML: IDM_UNDERLINE\n");
        cmd->cmdf = query_ns_edit_status(This, NSCMD_UNDERLINE);
        break;
    case IDM_HORIZONTALLINE:
        TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
        cmd->cmdf = query_ns_edit_status(This, NULL);
        break;
    case IDM_ORDERLIST:
        TRACE("CGID_MSHTML: IDM_ORDERLIST\n");
        cmd->cmdf = query_ns_edit_status(This, NSCMD_OL);
        break;
    case IDM_UNORDERLIST:
        TRACE("CGID_MSHTML: IDM_HORIZONTALLINE\n");
        cmd->cmdf = query_ns_edit_status(This, NSCMD_UL);
        break;
    case IDM_INDENT:
        TRACE("CGID_MSHTML: IDM_INDENT\n");
        cmd->cmdf = query_ns_edit_status(This, NULL);
        break;
    case IDM_OUTDENT:
        TRACE("CGID_MSHTML: IDM_OUTDENT\n");
        cmd->cmdf = query_ns_edit_status(This, NULL);
        break;
    case IDM_HYPERLINK:
        TRACE("CGID_MSHTML: IDM_HYPERLINK\n");
        cmd->cmdf = query_ns_edit_status(This, NULL);
        break;
    }

    return S_OK;
}

static INT_PTR CALLBACK hyperlink_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    static const WCHAR wszOther[] = {'(','o','t','h','e','r',')',0};
    static const WCHAR wszFile[] = {'f','i','l','e',':',0};
    static const WCHAR wszFtp[] = {'f','t','p',':',0};
    static const WCHAR wszHttp[] = {'h','t','t','p',':',0};
    static const WCHAR wszHttps[] = {'h','t','t','p','s',':',0};
    static const WCHAR wszMailto[] = {'m','a','i','l','t','o',':',0};
    static const WCHAR wszNews[] = {'n','e','w','s',':',0};

    switch (msg)
    {
        case WM_INITDIALOG:
        {
            INT def_idx;
            HWND hwndCB = GetDlgItem(hwnd, IDC_TYPE);
            HWND hwndURL = GetDlgItem(hwnd, IDC_URL);
            INT len;

            SetWindowLongPtrW(hwnd, DWLP_USER, lparam);

            SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszOther);
            SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszFile);
            SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszFtp);
            def_idx = SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszHttp);
            SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszHttps);
            SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszMailto);
            SendMessageW(hwndCB, CB_INSERTSTRING, -1, (LPARAM)wszNews);
            SendMessageW(hwndCB, CB_SETCURSEL, def_idx, 0);

            /* force the updating of the URL edit box */
            SendMessageW(hwnd, WM_COMMAND, MAKEWPARAM(IDC_TYPE, CBN_SELCHANGE), (LPARAM)hwndCB);

            SetFocus(hwndURL);
            len = SendMessageW(hwndURL, WM_GETTEXTLENGTH, 0, 0);
            SendMessageW(hwndURL, EM_SETSEL, 0, len);

            return FALSE;
        }
        case WM_COMMAND:
            switch (wparam)
            {
                case MAKEWPARAM(IDCANCEL, BN_CLICKED):
                    EndDialog(hwnd, wparam);
                    return TRUE;
                case MAKEWPARAM(IDOK, BN_CLICKED):
                {
                    BSTR *url = (BSTR *)GetWindowLongPtrW(hwnd, DWLP_USER);
                    HWND hwndURL = GetDlgItem(hwnd, IDC_URL);
                    INT len = GetWindowTextLengthW(hwndURL);
                    *url = SysAllocStringLen(NULL, len + 1);
                    GetWindowTextW(hwndURL, *url, len + 1);
                    EndDialog(hwnd, wparam);
                    return TRUE;
                }
                case MAKEWPARAM(IDC_TYPE, CBN_SELCHANGE):
                {
                    HWND hwndURL = GetDlgItem(hwnd, IDC_URL);
                    INT item;
                    INT len;
                    LPWSTR type;
                    LPWSTR url;
                    LPWSTR p;
                    static const WCHAR wszSlashSlash[] = {'/','/'};

                    /* get string of currently selected hyperlink type */
                    item = SendMessageW((HWND)lparam, CB_GETCURSEL, 0, 0);
                    len = SendMessageW((HWND)lparam, CB_GETLBTEXTLEN, item, 0);
                    type = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
                    SendMessageW((HWND)lparam, CB_GETLBTEXT, item, (LPARAM)type);

                    if (!strcmpW(type, wszOther))
                        *type = '\0';

                    /* get current URL */
                    len = GetWindowTextLengthW(hwndURL);
                    url = HeapAlloc(GetProcessHeap(), 0, (len + strlenW(type) + 3) * sizeof(WCHAR));
                    GetWindowTextW(hwndURL, url, len + 1);

                    /* strip off old protocol */
                    p = strchrW(url, ':');
                    if (p && p[1] == '/' && p[2] == '/')
                        p += 3;
                    if (!p) p = url;
                    memmove(url + (*type != '\0' ? strlenW(type) + 2 : 0), p, (len + 1 - (p - url)) * sizeof(WCHAR));

                    /* add new protocol */
                    if (*type != '\0')
                    {
                        memcpy(url, type, (strlenW(type) + 1) * sizeof(WCHAR));
                        if (strcmpW(type, wszMailto) && strcmpW(type, wszNews))
                            memcpy(url + strlenW(type), wszSlashSlash, sizeof(wszSlashSlash));
                    }

                    SetWindowTextW(hwndURL, url);

                    HeapFree(GetProcessHeap(), 0, url);
                    HeapFree(GetProcessHeap(), 0, type);
                    return TRUE;
                }
            }
            return FALSE;
        case WM_CLOSE:
            EndDialog(hwnd, IDCANCEL);
            return TRUE;
        default:
            return FALSE;
    }
}

static HRESULT exec_hyperlink(HTMLDocument *This, DWORD cmdexecopt, VARIANT *in, VARIANT *out)
{
    nsAString href_str, ns_url;
    nsIHTMLEditor *html_editor;
    nsIDOMHTMLElement *anchor_elem;
    cpp_bool insert_link_at_caret;
    nsISelection *nsselection;
    BSTR url = NULL;
    INT ret;
    HRESULT hres = E_FAIL;

    static const WCHAR aW[] = {'a',0};
    static const WCHAR hrefW[] = {'h','r','e','f',0};

    TRACE("%p, 0x%x, %p, %p\n", This, cmdexecopt, in, out);

    if (cmdexecopt == OLECMDEXECOPT_DONTPROMPTUSER)
    {
        if (!in || V_VT(in) != VT_BSTR)
        {
            WARN("invalid arg\n");
            return E_INVALIDARG;
        }
        url = V_BSTR(in);
    }
    else
    {
        ret = DialogBoxParamW(hInst, MAKEINTRESOURCEW(IDD_HYPERLINK), NULL /* FIXME */, hyperlink_dlgproc, (LPARAM)&url);
        if (ret != IDOK)
            return OLECMDERR_E_CANCELED;
    }

    if(!This->doc_node->nsdoc) {
        WARN("NULL nsdoc\n");
        return E_UNEXPECTED;
    }

    nsselection = get_ns_selection(This);
    if (!nsselection)
        return E_FAIL;

    /* create an element for the link */
    create_nselem(This->doc_node, aW, &anchor_elem);

    nsAString_InitDepend(&href_str, hrefW);
    nsAString_InitDepend(&ns_url, url);
    nsIDOMHTMLElement_SetAttribute(anchor_elem, &href_str, &ns_url);
    nsAString_Finish(&href_str);

    nsISelection_GetIsCollapsed(nsselection, &insert_link_at_caret);

    /* create an element with text of URL */
    if (insert_link_at_caret) {
        nsIDOMNode *text_node, *unused_node;

        nsIDOMHTMLDocument_CreateTextNode(This->doc_node->nsdoc, &ns_url, (nsIDOMText **)&text_node);

        /* wrap the <a> tags around the text element */
        nsIDOMHTMLElement_AppendChild(anchor_elem, text_node, &unused_node);
        nsIDOMNode_Release(text_node);
        nsIDOMNode_Release(unused_node);
    }

    nsAString_Finish(&ns_url);

    nsIEditor_QueryInterface(This->doc_obj->nscontainer->editor, &IID_nsIHTMLEditor, (void **)&html_editor);
    if (html_editor) {
        nsresult nsres;

        if (insert_link_at_caret) {
            /* add them to the document at the caret position */
            nsres = nsIHTMLEditor_InsertElementAtSelection(html_editor, (nsIDOMElement*)anchor_elem, FALSE);
            nsISelection_SelectAllChildren(nsselection, (nsIDOMNode*)anchor_elem);
        }else /* add them around the selection using the magic provided to us by nsIHTMLEditor */
            nsres = nsIHTMLEditor_InsertLinkAroundSelection(html_editor, (nsIDOMElement*)anchor_elem);

        nsIHTMLEditor_Release(html_editor);
        hres = NS_SUCCEEDED(nsres) ? S_OK : E_FAIL;
    }

    nsISelection_Release(nsselection);
    nsIDOMHTMLElement_Release(anchor_elem);

    if (cmdexecopt != OLECMDEXECOPT_DONTPROMPTUSER)
        SysFreeString(url);

    TRACE("-- 0x%08x\n", hres);
    return hres;
}

static HRESULT query_selall_status(HTMLDocument *This, OLECMD *cmd)
{
    TRACE("(%p)->(%p)\n", This, cmd);

    cmd->cmdf = OLECMDF_SUPPORTED|OLECMDF_ENABLED;
    return S_OK;
}

const cmdtable_t editmode_cmds[] = {
    {IDM_DELETE,          query_edit_status,    exec_delete},
    {IDM_FONTNAME,        query_edit_status,    exec_fontname},
    {IDM_FONTSIZE,        query_edit_status,    exec_fontsize},
    {IDM_SELECTALL,       query_selall_status , exec_selectall},
    {IDM_FORECOLOR,       query_edit_status,    exec_forecolor},
    {IDM_BOLD,            query_edit_status,    exec_bold},
    {IDM_ITALIC,          query_edit_status,    exec_italic},
    {IDM_JUSTIFYCENTER,   query_justify,        exec_justifycenter},
    {IDM_JUSTIFYRIGHT,    query_justify,        exec_justifyright},
    {IDM_JUSTIFYLEFT,     query_justify,        exec_justifyleft},
    {IDM_FONT,            NULL,                 exec_font},
    {IDM_UNDERLINE,       query_edit_status,    exec_underline},
    {IDM_HORIZONTALLINE,  query_edit_status,    exec_horizontalline},
    {IDM_ORDERLIST,       query_edit_status,    exec_orderlist},
    {IDM_UNORDERLIST,     query_edit_status,    exec_unorderlist},
    {IDM_INDENT,          query_edit_status,    exec_indent},
    {IDM_OUTDENT,         query_edit_status,    exec_outdent},
    {IDM_COMPOSESETTINGS, NULL,                 exec_composesettings},
    {IDM_HYPERLINK,       query_edit_status,    exec_hyperlink},
    {IDM_SETDIRTY,        NULL,                 exec_setdirty},
    {0,NULL,NULL}
};

void init_editor(HTMLDocument *This)
{
    update_doc(This, UPDATE_UI);

    set_ns_fontname(This, "Times New Roman");
}

HRESULT editor_is_dirty(HTMLDocument *This)
{
    cpp_bool modified;

    if(!This->doc_obj->nscontainer || !This->doc_obj->nscontainer->editor)
        return S_FALSE;

    nsIEditor_GetDocumentModified(This->doc_obj->nscontainer->editor, &modified);

    return modified ? S_OK : S_FALSE;
}

HRESULT setup_edit_mode(HTMLDocumentObj *doc)
{
    IMoniker *mon;
    HRESULT hres;

    if(doc->usermode == EDITMODE)
        return S_OK;

    doc->usermode = EDITMODE;

    if(doc->basedoc.window->mon) {
        CLSID clsid = IID_NULL;
        hres = IMoniker_GetClassID(doc->basedoc.window->mon, &clsid);
        if(SUCCEEDED(hres)) {
            /* We should use IMoniker::Save here */
            FIXME("Use CLSID %s\n", debugstr_guid(&clsid));
        }
    }

    if(doc->frame)
        IOleInPlaceFrame_SetStatusText(doc->frame, NULL);

    doc->basedoc.window->readystate = READYSTATE_UNINITIALIZED;

    if(doc->client) {
        IOleCommandTarget *cmdtrg;

        hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
        if(SUCCEEDED(hres)) {
            VARIANT var;

            V_VT(&var) = VT_I4;
            V_I4(&var) = 0;
            IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);

            IOleCommandTarget_Release(cmdtrg);
        }
    }

    if(doc->hostui) {
        DOCHOSTUIINFO hostinfo;

        memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
        hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
        hres = IDocHostUIHandler_GetHostInfo(doc->hostui, &hostinfo);
        if(SUCCEEDED(hres))
            /* FIXME: use hostinfo */
            TRACE("hostinfo = {%u %08x %08x %s %s}\n",
                    hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
                    debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
    }

    update_doc(&doc->basedoc, UPDATE_UI);

    if(doc->basedoc.window->mon) {
        /* FIXME: We should find nicer way to do this */
        remove_target_tasks(doc->basedoc.task_magic);

        mon = doc->basedoc.window->mon;
        IMoniker_AddRef(mon);
    }else {
        static const WCHAR about_blankW[] = {'a','b','o','u','t',':','b','l','a','n','k',0};

        hres = CreateURLMoniker(NULL, about_blankW, &mon);
        if(FAILED(hres)) {
            FIXME("CreateURLMoniker failed: %08x\n", hres);
            return hres;
        }
    }

    hres = IPersistMoniker_Load(&doc->basedoc.IPersistMoniker_iface, TRUE, mon, NULL, 0);
    IMoniker_Release(mon);
    if(FAILED(hres))
        return hres;

    if(doc->ui_active) {
        if(doc->ip_window)
            call_set_active_object(doc->ip_window, NULL);
        if(doc->hostui)
            IDocHostUIHandler_HideUI(doc->hostui);
    }

    if(doc->ui_active) {
        RECT rcBorderWidths;

        if(doc->hostui)
            IDocHostUIHandler_ShowUI(doc->hostui, DOCHOSTUITYPE_AUTHOR,
                    &doc->basedoc.IOleInPlaceActiveObject_iface, &doc->basedoc.IOleCommandTarget_iface,
                    doc->frame, doc->ip_window);

        if(doc->ip_window)
            call_set_active_object(doc->ip_window, &doc->basedoc.IOleInPlaceActiveObject_iface);

        memset(&rcBorderWidths, 0, sizeof(rcBorderWidths));
        if(doc->frame)
            IOleInPlaceFrame_SetBorderSpace(doc->frame, &rcBorderWidths);
    }

    return S_OK;
}


Sports minister Rajyavardhan Singh Rathore felicitated Indian athletes after their splendid show at the recently concluded Asian Games. Indian athletes help in getting the best-ever medal haul for the country in Asian Games 2018. While congratulating the medal winners, Rathore said that the countdown for 2020 Olympics has started and they should think about that instead of just being satisfied with the Asian Games medal. The function was held to felicitate the medal winners with cash awards.


This morning, 11 years ago I woke up on a beach in DelRay Beach, FL and quietly started my recovery clock over. The night before I had relapsed on my 90th day clean/sober on a couple of glasses of wine. I didn't tell a soul and only 2 friends I had gone down to visit from rehab knew about it. I just kept on going as if I didn't drink that wine. 9 months later I falsely claimed my Year chip in my 12th step group and a few weeks later moved back to Jackson, WY never uttering a word. What the hell right? Cocaine was my drug of choice after all. It was only 1 night and I didn't even get drunk. Well, that saying, "your secrets keep you sick" started to eat away at me.
Upon becoming a member of a different 12th step group in Jackson (as the one I was a member of in Spartanburg was not available at the time here) I started working the 12 steps out of this particular fellowship. I had started dating Cody, reconnected with some old friend who were also in recovery, and making new friends in the fellowship. My network here was completely oblivious to my previous history other than what I had shared. My secret started to eat me alive and I knew that I needed to get honest. After all, honesty is a key component to recovery. I shared my secret with my sponsor and close recovery friends.
Coincidentally, or not, my 9th step arrived and it was the beginning of February. On February 4th, 2008 I received my true 100% real 1st year of recovery without the use of drugs (alcohol is a drug) and got honest with my fellowship here in Wyoming. It was beyond scary to admit my wrongs and speak my truth. Fear is a scary deal but guess what? My feelings did not kill me and no one loved me any less.
So today, I celebrate 11 years of authentic recovery. I no longer have to let my fears dictate my life, I have freedom from addiction and a solution to live my life happy, joyous, and free! Today I choose to not pick up no matter what. I'm no longer a slave to myself and my addiction. Today, I have so many miracles in my life as a direct result of my sobriety I could write a series of novels about them. I am by no means perfect, I have not arrived, and lord knows I'm often a hot mess! Fortunately though I have a design for living and if I choose to live in the solution I have a chance at another 24 hours.
Our 1st Family photo of 2019! 2 recovering parents and our son, who praise God has never seen us drink/use and God willing, never will!
For a gal like myself who was in the grips of addiction for 17 solid years, my life today is indeed a miracle and filled with grace. If you are reading this and are sick and tired of being sick and tired, please know that there is hope! There is a way out and I'm always happy to share what has worked for me. As I mentioned previously, I'm not perfect, I could relapse at any moment if I make a poor choice and not utilize all the tools that have been so freely given to me. Thank God for a connection to a higher power that has helped me thus far stay on the right path, a network of fellow folks just like me whom have and continue to walk this path, and all the love and support from my family and close friends. You each save me from myself daily.
I do not write this for kudos, as much as I do love them, but I do so as an example that recovery is possible! You are worth it! We all deserve a life worth living!
2019 fun with my family!! Fly fishing has been a blessing and a great tool to practice active meditation, patience, and quality time with my family over a common bond!!
Thank you each for playing a roll in my story. Be it past or present I'm grateful for the hundreds of connections I've made in life and via social media. Today is a good day for a great day!


Thanks to the arrival of the grader, this is how it looks this morning!
The tracks – flood affected or not – have needed attention. Zoe and I had devised a game where we sang songs as the UTV bobbed over the corrugations and let our voices quaver.
The tracks were "good enough" though and we spent our farm budget on other things. The floods changed all that and, rather than spend tens of thousands of dollars on fresh gravel, we've taken the more conservative route of grading first, then seeing what else needs to be done in autumn.
For now, it feels like Christmas has come early. We practically glide along the tracks and can sing "Zoe Macdonald had a farm" at the tops of our voices without the slightest wobble!


LED light effect, Plug in USB and the earphones will light, LED light effect to keep your passion on play games. More enjoy.
Noise-canceling microphone, Reduce distracting background noise, Easy to rotate to the best position for clearest voice.
Adjustable padded headband, fit with ear, and plush padding, more comfortable.
earmuffs Comfortable, Breathable material is helpful to reduce heat and moisture during intense games. keep your ears feeling good even on long time use.
3.5mm audio jack and USB design, USB for LED light.
Works for games, movies, music, Skype and Phone Call.


A top notch filleting knife from Snowbee. This knife has a thin, flexible 7" stainless steel blade with a full length tang and distinctive pakka wood handle.
- A thin, flexible, 7" blade made from 420 grade high-carbon Stainless Steel.
- A one piece blade, bolster and full tang construction.
- A 'Pakka' wood handle that is strong, durable and moisture resistant (Dishwasher safe).


Converse Chuck Taylor All Star Street Hiker Hi-Tops - Black Dominate the urban jungle this winter courtesy of Converse and these Chuck Taylor All Star Street Hiker Hi-Tops. A durable outsole gives grip and traction on wet and slippery surfaces to keep you steady on the move, while the iconic Hi-Top silhouette and fresh white trims are nods to their infamous heritage. Secured with laces and metal eyelets, they're a tough pair that you'll reach for whenever the elements are against you! Complete your look with a rubber parka coat, jeans, and a jumper. Grabbing a beanie and scarf when things get really cold.


Top UK promotion Cage Warriors Fighting Championship has finalised what is arguably the biggest women's fight in its eight-year history. Cage Warriors champ Rosi "The Surgeon" Sexton will face Roxanne "The Happy Warrior" Modafferi in a 125-pound bout at CWFC 40 on February 26, 2011.
MMARising.com first learned of the fight in early December and has since confirmed the matchup with multiple sources close to the negotiations. Both fighters have signed bout agreements. The fight will serve as Modafferi's debut at 125 pounds, but will not be contested for Sexton's CWFC title.
Sexton (11-2-0) was scheduled to take part in the inaugural Bellator 115-pound women's tournament earlier this year, but a knockout loss to Zoila Frausto prior to the tournament forced her to the sidelines. Just as she did after suffering the first loss of her career, Sexton bounced back with an impressive win in November, stopping "Slick" Sally Krumdiack with punches in the second round. The fight marked the first time that Krumdiack had ever been stopped by strikes, and was also just the second TKO win of Sexton's career. While her immediate future in Bellator remains to be decided, Sexton will have a very tough fight on her hands in February.
Modafferi (15-6-0), whose focus is currently on a December 30th matchup with Hitomi "Girlfight Monster" Akano at SRC: "Soul of Fight," will return to action two months later to take on Sexton in what will be Modafferi's first fight at 125 pounds. The American, who lives and trains in Japan, has won eight of her last ten fights and totalled big victories over current Strikeforce champ Marloes Coenen and DaMMAge Fight League ace Tara LaRosa. A bid for the Strikeforce Women's Welterweight Championship ended in defeat, but Modafferi will have a chance to pick up another big win before facing Sexton when she meets Akano in ten days.
Cage Warriors Fighting Championship 40 takes place on February 26th at the HMV Forum in Kentish Town, North London, England. The bout between Sexton and Modafferi is expected to be officially announced by the promotion before the end of this month.
If the cut goes well Roxanne could be a monster at 125. I'm surprised they didn't do a catch weight at 130 if they don't want it to be a title fight.
My management want to keep me at 125 for the time being. After all, I may still need to be able to make 115.
Roxy will be to big for Rosi.
I like Roxy by TKO.
Yeah, can't wait for this, go Rosi!!!
Will be a very nice fight. Both Roxy and Rosi have hearts of a warrior, and both bring great story lines to the fight. Both are technical and accomplished too.


text:
Home Music Reviews Album Reviews 'TajMo' Finds Keb' Mo' and Taj Mahal In Top Form
'TajMo' Finds Keb' Mo' and Taj Mahal In Top Form
'TajMo' finds Keb' Mo' and Taj Mahal joined together, making beautiful music...
Barry Kerzner
Roots Music
Sometimes the universe smiles a sly little smile, and music fans get something we long for. Born Henry Saint Clair Fredericks in 1942, Taj Mahal has been making great music for decades now, coming to the attention of a wide audience with his initial release Taj Mahal in 1968 and following that up with The Natch'l Blues in 1969. These two Columbia label albums are the bedrock that Taj Mahal would build the foundation of a remarkable career upon. To date he has been nominated for nine Grammy Awards, receiving two. In 2006 he received the Historical Album of the Year BMA for The Essential Taj Mahal. Also in 2006, he was designated the official Blues Artist of the Commonwealth of Massachusetts.
Born Kevin Roosevelt Moore in 1951, Keb' Mo' came to folks' attention with his Okeh debut in 1994, aptly titled Keb' Mo'. He won the W.C. Handy Award (previous name for the BMA) for Best Country/Acoustic Blues Album of the Year, 1995 for this remarkable album. 12 albums on he's been nominated for eight Grammy Awards, winning three. He is a master at spinning yarns that weave country, delta, and other blues forms into modern interpretations that still give a nod to the ancestors from which they sprang.
TajMo finds Keb' Mo' and Taj Mahal joined together, making beautiful music in the presence of one another, and with one another. Fortunately, with this album, they share their experience and music with all of us as well. The album boasts 11 tracks and has a running time of just over 45 minutes, which will seem woefully short when it's over!
There are several things that become apparent from the beginning. These two gentlemen are really enjoying each other, building the music, each seeing what the other offers and then serving up their own delight to enhance the whole. This is not competition, but more two masters, two friends, two musicians who admire each others' work, seeing where their friend will take them, as the music celebrates their journey together.
Guests joining them include Bonnie Raitt, Joe Walsh, Sheila E. and Lizz Wright. The album is self-produced, and the love afforded these tracks in the recording process by Zach Allen, John Caldwell, and Casey Wasner is undeniable. The music almost jumps off the album, and the sound is warm and clear thanks to a proper mix courtesy of Ross Hogarth.
We all experience music differently. On one level, this album is universally pleasing as it nudges, pushes, lifts up, and touches the soul, drinking in its goodness. Naturally, everyone also has their favorites. We enjoyed "Don't Leave Me Here," with its serious backbeat, horn fills, organ textures and guitar fills, and "Shake Me In Your Arms," again with an incredible back beat, and strong guitar lines with a winning solo by Joe Walsh.
Another track we appreciated was "That's Who I Am," with a seeming symphony of guitars including electric and slide by Keb' Mo', resonator by Keb' Mo' and Taj Mahal, and a great mandolin line by Colin Linden. "Ain't Nobody Talkin'" featured a slow groove, slow, with brilliant harmonies and textures, and guitar lines, while "Soul" had an infectious Caribbean vibe. John Mayer's "Waiting On The World To Change" closes the album and is a completely unique performance of this modern classic. Keb' Mo' plays bass, percussion, acoustic guitar and provides the vocals, with Taj Mahal also on acoustic guitar and vocals, with Bonnie Raitt providing backing vocals as well. The simplicity of the presentation is what endears this performance to listeners, along with the beauty of the acoustic rendering, and even a bit of scat singing too.
Don't pass up this opportunity to spend time with these two masters as they share their music with you. That would be a real shame indeed.
TajMo by Keb' Mo' and Taj Mahal
Label: Concord Records
Release Date: May 5th, 2017
Keb' Mo'
TajMo
Concord Records
Previous articleStax Records Announces 60th Anniversary Plans
Next articleStrongman Reminds Us There's 'No Time Like Now'

redpajama_set_name: RedPajamaCommonCrawl


I want to open each commits in pull request for reviewing code.
I launched Toggle Monochrome Bookmarklet.
This article said "Lightness is important. Association each items is also important.". I wrote Toggle Monochrome, this is easy to check web page as grayscale. I confirmed this on chrome 33.


1. Cut potatoes lengthwise into very thin slices.
2. Place the slices in a large bowl and coat them with olive oil and salt.
3. Pre-heat grill in medium high heat.
4. Place the grill pan on grill and allow it to heat.
5. Arrange the slices of potatoes on the pan forming a single layer and allow them to cook for 5 minutes per side.
6. Repeat the same process with the remaining slices of potato and serve with a dip of your choice.
Feel free to comment or share your thoughts on this Grilled Potato Chips Recipe from Awesome Cuisine.


FRIDAY BLOGPOST: Next week's Tuesday Shoesday has come early on the Cassiefairy blog. For good reason – It's not everyday that I'm rendered speechless by a pair of shoes but when I read the news in the Telegraph on Friday I could not believe my eyes. Nike are releasing the Marty McFly's trainers from the cult film Back to the Future 2!
And to make my heart beat even faster, there's only 1500 pairs being released – and sold on Ebay to raise money for the Michael J Fox Foundation for Parkinson's disease research. I now know there is no way I'll be getting my hands on a pair of these iconic trainers – but it won't stop me trying to win one of those auctions!
In the 1989 film, Marty McFly wore the shoes in a futuristic 2015 world, and now in 2011 the dream has become a reality! Surely flying cars are only a couple of years away too!
I never realised I was such a Back to the Future geek! I'm so excited!
University Freshers – some advice from a graduate!
Upcycling shipping containers into a garden offices – is it do-able?
Preparing your bedroom for Santa's visit!


text:
Q: ng-show not working in datatables columns I am creating a table in angular using datatables. I've use a value from the scope and I compare this value with the data received.
"columns": [{ data: null, render: function ( data, type, row ) {
var roleid =angular.element('#TextkeysController').scope().currentRole;
return '
connected

Not connected
';
}, name: 'connect', "className":"center"}]

When I load the data both button appear in the row - column and the condition only apply when I click in a ng-click action.
Could someone help me to know why this happen?

A: Obviously angular is not aware of the HTML injected by dataTables. In this cases I use to $compile the rendered content in a drawCallback :
withOption('drawCallback', function() {
   $scope.$apply($compile(angular.element('#tableId'))($scope))
}

where #tableId is the id of your table. But in general this is a little bit messed up, imho. When I need specific angular directives attached to dataTables rows or columns I render the angular way with datatable="ng". Slower but more clean and maintainable.

redpajama_set_name: RedPajamaStackExchange


When U.S. Attorney General Alberto Gonzales stunned the Senate Judiciary Committee by asserting that the right of habeas corpus — which enables individuals to challenge the legality of their imprisonment — is not constitutionally protected, it marked a chilling new assertion of executive power over the judiciary. But it was no aberration.
Indeed, following on the heels of a speech a day earlier in which Gonzales sharply criticized "activist judges" with the audacity to consider legal issues involving national security, his words are consistent in revealing an objective that has less to do with protecting Americans from terrorist-coddling jurists than with cowing the judiciary into abrogating its role as a co-equal branch of government — and thereby weakening restraints on presidential and congressional authority.
By now, of course, most of us recognize the national security imperative as one of the more reliable standards from White House aide Karl Rove's dog-eared playbook. But long before the terrorist attacks of Sept. 11, 2001, political efforts to demonize the judiciary for its proper function as the guardian of constitutional liberties were under way. Indeed, "activist judges" have been a bugaboo for social conservatives for decades, and were commonly cited by George W. Bush in his 2000 presidential campaign.
Unfortunately, the political effort to de-legitimize judicial independence isn't limited to verbal attacks from the bully pulpit, which judges necessarily lack. The Bush administration and its congressional allies have also demonstrated a propensity to stiff-arm the courts in crafting public policy.
In an act of stunning congressional defiance, the bill's sponsors made no pretense of the fact that their intent was not to comply with the high court's constitutional ruling, but to overrule it.
Since becoming law, the act has been found unconstitutional in federal courts in three jurisdictions — including San Francisco, where my office intervened in the case alongside Planned Parenthood. The matter is now again before the high court, and what is at stake in the decision due this summer is far more than the future of reproductive rights in America.
Our nation's highest court has never allowed Congress to overturn a constitutional precedent by any means other than a constitutional amendment. Should it do so now, it would self-inflict a devastating blow to judicial independence. Politicians in the legislative and executive branches — Republicans and Democrats alike — will be on notice that judicial rulings may be ignored or overruled.
Our nation is at a point in its history in which the tension between increasingly complex national security obligations and the need to protect civil liberties is particularly strong. It is times like these when each branch of government must fulfill its constitutional duties with firm conviction.
"There is no liberty, if the power of judging be not separated from the legislative, and executive powers," wrote Alexander Hamilton, quoting Montesquieu, in The Federalist No. 78.
Now more than ever, Americans need to see attacks on "activist judges" for what they are: a bully tactic intended to enfeeble a coordinate branch of government. A vibrant, independent judiciary must fulfill its obligation in enforcing a Constitution that protects us all.


The Orabella's Blog...: Fireball "Meteor" Injures Hundreds In Central Russia.
Fireball "Meteor" Injures Hundreds In Central Russia.
A Meteor is a small body of matter from outer space that enters the earth's atmosphere, appearing as a streak of light. It is also called a shooting star.
This morning it streaked through the skies above Russia's Urals mountains, before it exploded with a flash and boom that shattered glass in buildings and left hundreds of people with cuts and bruises.
As a result of the shock waves caused by the blast, about 270 buildings have been damaged, mostly with broken glasses. Kindergartens, schools and hospital are among the buildings that were affected.
There is a continuous rise to the number of people injured from across wide areas. 725 people has sought medical help with 34 of them hospitalized at noon time in Moscow.
The President of Russia is thanking God that no big fragment of this shooting star has fallen in a populated area, it would have been really drastic. A large meteor fragment landed in a lake near a town in Chelyabinsk region, Russia.
Residents of this town told BBC News that "We saw a very bright light and then there was a kind of a track, white and yellow in the sky. The explosion was so strong that some windows in our buildings and in the city in general were broken. It was quite extraordinary"
Officials say the reason behind this incident is that a large meteor partially burned up in the lower atmosphere, resulting in fragments falling earthwards.