(* OCaml-Win32
 * win32_listview.ml
 * Copyright (c) 2002-2004 by Harry Chomsky
 *
 * 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 library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *)

open Win32_core

(********************************************************************)
(* User Interface: Windows User Experience: Windows Shell: SDK: Windows Controls: Individual Control Information: List-View Controls *)

let wc_listview = "SysListView32"

type listview_extended_style =
    LVS_EX_CHECKBOXES
  | LVS_EX_FLATSB
  | LVS_EX_FULLROWSELECT
  | LVS_EX_GRIDLINES
  | LVS_EX_HEADERDRAGDROP
  | LVS_EX_INFOTIP
  | LVS_EX_MULTIWORKAREAS
  | LVS_EX_ONECLICKACTIVATE
  | LVS_EX_REGIONAL
  | LVS_EX_SUBITEMIMAGES
  | LVS_EX_TRACKSELECT
  | LVS_EX_TWOCLICKACTIVATE
  | LVS_EX_UNDERLINECOLD
  | LVS_EX_UNDERLINEHOT

type lvitem_state = {
    lvis_activating : bool option;
    lvis_cut : bool option;
    lvis_drophilited : bool option;
    lvis_focused : bool option;
    lvis_selected : bool option;
    lvis_overlay : int option;
    lvis_state_image : int option }
let default_lvitem_state = {
    lvis_activating = None;
    lvis_cut = None;
    lvis_drophilited = None;
    lvis_focused = None;
    lvis_selected = None;
    lvis_overlay = None;
    lvis_state_image = None }

type lvitem = {
    lvi_item : int;
    lvi_sub_item : int;
    lvi_state : lvitem_state option;
    lvi_text : common_control_text option;
    lvi_image : common_control_image_index option;
    lvi_lparam : int32 option;
    lvi_indent : int option;
    lvi_norecompute : bool }
let default_lvitem = {
    lvi_item = 0;
    lvi_sub_item = 0;
    lvi_state = None;
    lvi_text = None;
    lvi_image = None;
    lvi_lparam = None;
    lvi_indent = None;
    lvi_norecompute = false }

type lvitem_state_component =
    Lvis_activating
  | Lvis_cut
  | Lvis_drophilited
  | Lvis_focused
  | Lvis_selected
  | Lvis_overlay
  | Lvis_state_image
let all_lvitem_state_components = [
    Lvis_activating;
    Lvis_cut;
    Lvis_drophilited;
    Lvis_focused;
    Lvis_selected;
    Lvis_overlay;
    Lvis_state_image ]

type lvitem_component =
    Lvif_state of lvitem_state_component list
  | Lvif_text of int
  | Lvif_image
  | Lvif_param
  | Lvif_indent
let all_lvitem_components = [
    Lvif_state all_lvitem_state_components;
    Lvif_text 256;
    Lvif_image;
    Lvif_param;
    Lvif_indent ]

type lvcolumn_justification =
    LVCFMT_CENTER
  | LVCFMT_LEFT
  | LVCFMT_RIGHT
type lvcolumn_format_option =
    LVCFMT_BITMAP_ON_RIGHT
  | LVCFMT_COL_HAS_IMAGES
  | LVCFMT_IMAGE
type lvcolumn_format = {
    lvcf_justify : lvcolumn_justification;
    lvcf_options : lvcolumn_format_option list }
type lvcolumn = {
    lvc_format : lvcolumn_format option;
    lvc_width : int option;
    lvc_text : string option;
    lvc_sub_item : int option;
    lvc_image : int option;
    lvc_order : int option }
let default_lvcolumn = {
    lvc_format = None;
    lvc_width = None;
    lvc_text = None;
    lvc_sub_item = None;
    lvc_image = None;
    lvc_order = None }

type lvcolumn_component =
    Lvcf_fmt
  | Lvcf_width
  | Lvcf_text of int
  | Lvcf_subitem
  | Lvcf_image
  | Lvcf_order
let all_lvcolumn_components = [
    Lvcf_fmt;
    Lvcf_width;
    Lvcf_text 256;
    Lvcf_subitem;
    Lvcf_image;
    Lvcf_order ]

type lvfind_target =
    Lvft_string of string
  | Lvft_partial_string of string
  | Lvft_lparam of int32
type lvfind_order =
    Lvfo_all
  | Lvfo_after of int
  | Lvfo_after_wrap of int
  | Lvfo_spatial of point * virtual_key_code
type lvfindinfo = {
    lvfi_target : lvfind_target;
    lvfi_order : lvfind_order }

type lvbkimage_source =
    Lvbkis_none
  | Lvbkis_hbitmap of hbitmap
  | Lvbkis_url of string
type lvbkimage_style =
    LVBKIF_STYLE_NORMAL
  | LVBKIF_STYLE_TILE
type lvbkimage = {
    lvbki_source : lvbkimage_source;
    lvbki_style : lvbkimage_style;
    lvbki_x_offset_percent : int;
    lvbki_y_offset_percent : int }

type listview_which_image_list =
    LVSIL_NORMAL
  | LVSIL_SMALL
  | LVSIL_STATE

type listview_item_portion =
    LVIR_BOUNDS
  | LVIR_ICON
  | LVIR_LABEL
  | LVIR_SELECTBOUNDS

let lv_max_workareas = 16

type listview_hit_test_direction =
    LVHT_ABOVE
  | LVHT_BELOW
  | LVHT_TOLEFT
  | LVHT_TORIGHT
type listview_hit_test_part =
    LVHT_ONITEMICON
  | LVHT_ONITEMLABEL
  | LVHT_ONITEMSTATEICON
type listview_hit_test_result =
    Lvhtr_outside of listview_hit_test_direction list
  | Lvhtr_nowhere
  | Lvhtr_onitem of int * int * listview_hit_test_part

external listview_get_check_state : wnd:hwnd -> item:int -> bool = "listview_get_check_state"

external listview_set_check_state : wnd:hwnd -> item:int -> check:bool -> unit = "listview_set_check_state"

(* Styles *)

type listview_style_option =
    LVS_ALIGNLEFT
  | LVS_ALIGNTOP
  | LVS_AUTOARRANGE
  | LVS_EDITLABELS
  | LVS_ICON
  | LVS_LIST
  | LVS_NOCOLUMNHEADER
  | LVS_NOLABELWRAP
  | LVS_NOSCROLL
  | LVS_NOSORTHEADER
  | LVS_OWNERDATA
  | LVS_OWNERDRAWFIXED
  | LVS_REPORT
  | LVS_SHAREIMAGELISTS
  | LVS_SHOWSELALWAYS
  | LVS_SINGLESEL
  | LVS_SMALLICON
  | LVS_SORTASCENDING
  | LVS_SORTDESCENDING

external listview_style_of_option : listview_style_option -> style = "listview_style_of_option"

let listview_style_of_options = special_style_of_options ~special_func:listview_style_of_option

type listview_mode =
    Lvs_icon
  | Lvs_smallicon
  | Lvs_list
  | Lvs_report
external get_listview_mode : style:style -> listview_mode = "get_listview_mode"
external set_listview_mode : style:style -> mode:listview_mode -> style = "set_listview_mode"

(* Messages *)

let lvm_first = 0x1000

let lvm_approximateviewrect = lvm_first + 64
external pack_lvm_approximateviewrect : count:int -> size:size -> message_contents = "pack_lvm_approximateviewrect"
external unpack_lvm_approximateviewrect : message_result -> size = "unpack_lvm_approximateviewrect"
let issue_lvm_approximateviewrect ~sender ~count ~size = unpack_lvm_approximateviewrect (sender ~msg:(pack_lvm_approximateviewrect ~count ~size))

let lvm_arrange = lvm_first + 22
type listview_arrangement =
    LVA_ALIGNLEFT
  | LVA_ALIGNTOP
  | LVA_DEFAULT
  | LVA_SNAPTOGRID
external pack_lvm_arrange : arrangement:listview_arrangement -> message_contents = "pack_lvm_arrange"
external unpack_lvm_arrange : message_result -> unit = "unpack_lvm_arrange"
let issue_lvm_arrange ~sender ~arrangement = unpack_lvm_arrange (sender ~msg:(pack_lvm_arrange ~arrangement))

let lvm_createdragimage = lvm_first + 33
external issue_lvm_createdragimage : sender:message_sender -> item:int -> (himagelist * point) = "issue_lvm_createdragimage"

let lvm_deleteallitems = lvm_first + 9
let pack_lvm_deleteallitems = pack_simple_message ~id:lvm_deleteallitems
external unpack_lvm_deleteallitems : message_result -> unit = "unpack_lvm_deleteallitems"
let issue_lvm_deleteallitems ~sender = unpack_lvm_deleteallitems (sender ~msg:(pack_lvm_deleteallitems))

let lvm_deletecolumn = lvm_first + 28
external pack_lvm_deletecolumn : col:int -> message_contents = "pack_lvm_deletecolumn"
external unpack_lvm_deletecolumn : message_result -> unit = "unpack_lvm_deletecolumn"
let issue_lvm_deletecolumn ~sender ~col = unpack_lvm_deletecolumn (sender ~msg:(pack_lvm_deletecolumn ~col))

let lvm_deleteitem = lvm_first + 8
external pack_lvm_deleteitem : item:int -> message_contents = "pack_lvm_deleteitem"
external unpack_lvm_deleteitem : message_result -> unit = "unpack_lvm_deleteitem"
let issue_lvm_deleteitem ~sender ~item = unpack_lvm_deleteitem (sender ~msg:(pack_lvm_deleteitem ~item))

let lvm_editlabel = lvm_first + 23
external pack_lvm_editlabel : item:int -> message_contents = "pack_lvm_editlabel"
external unpack_lvm_editlabel : message_result -> hwnd = "unpack_lvm_editlabel"
let issue_lvm_editlabel ~sender ~item = unpack_lvm_editlabel (sender ~msg:(pack_lvm_editlabel ~item))

let lvm_ensurevisible = lvm_first + 19
external pack_lvm_ensurevisible : item:int -> partial_ok:bool -> message_contents = "pack_lvm_ensurevisible"
external unpack_lvm_ensurevisible : message_result -> unit = "unpack_lvm_ensurevisible"
let issue_lvm_ensurevisible ~sender ~item ~partial_ok = unpack_lvm_ensurevisible (sender ~msg:(pack_lvm_ensurevisible ~item ~partial_ok))

let lvm_finditem = lvm_first + 13
external issue_lvm_finditem : sender:message_sender -> info:lvfindinfo -> int option = "issue_lvm_finditem"

let lvm_getbkcolor = lvm_first + 0
let pack_lvm_getbkcolor = pack_simple_message ~id:lvm_getbkcolor
external unpack_lvm_getbkcolor : message_result -> color = "unpack_lvm_getbkcolor"
let issue_lvm_getbkcolor ~sender = unpack_lvm_getbkcolor (sender ~msg:pack_lvm_getbkcolor)

let lvm_getbkimage = lvm_first + 69
external issue_lvm_getbkimage : sender:message_sender -> max_length:int -> lvbkimage = "issue_lvm_getbkimage"

let lvm_getcallbackmask = lvm_first + 10
let pack_lvm_getcallbackmask = pack_simple_message ~id:lvm_getcallbackmask
external unpack_lvm_getcallbackmask : message_result -> lvitem_state_component list = "unpack_lvm_getcallbackmask"
let issue_lvm_getcallbackmask ~sender = unpack_lvm_getcallbackmask (sender ~msg:pack_lvm_getcallbackmask)

let lvm_getcolumn = lvm_first + 25
external issue_lvm_getcolumn :
    sender:message_sender ->
    col:int ->
    mask:lvcolumn_component list ->
    lvcolumn = "issue_lvm_getcolumn"

let lvm_getcolumnorderarray = lvm_first + 59
external issue_lvm_getcolumnorderarray : sender:message_sender -> count:int -> int array = "issue_lvm_getcolumnorderarray"

let lvm_getcolumnwidth = lvm_first + 29
external pack_lvm_getcolumnwidth : col:int -> message_contents = "pack_lvm_getcolumnwidth"
external unpack_lvm_getcolumnwidth : message_result -> int = "unpack_lvm_getcolumnwidth"
let issue_lvm_getcolumnwidth ~sender ~col = unpack_lvm_getcolumnwidth (sender ~msg:(pack_lvm_getcolumnwidth ~col))

let lvm_getcountperpage = lvm_first + 40
let pack_lvm_getcountperpage = pack_simple_message ~id:lvm_getcountperpage
external unpack_lvm_getcountperpage : message_result -> int = "unpack_lvm_getcountperpage"
let issue_lvm_getcountperpage ~sender = unpack_lvm_getcountperpage (sender ~msg:pack_lvm_getcountperpage)

let lvm_geteditcontrol = lvm_first + 24
let pack_lvm_geteditcontrol = pack_simple_message ~id:lvm_geteditcontrol
external unpack_lvm_geteditcontrol : message_result -> hwnd = "unpack_lvm_geteditcontrol"
let issue_lvm_geteditcontrol ~sender = unpack_lvm_geteditcontrol (sender ~msg:pack_lvm_geteditcontrol)

let lvm_getextendedlistviewstyle = lvm_first + 55
let pack_lvm_getextendedlistviewstyle = pack_simple_message ~id:lvm_getextendedlistviewstyle
external unpack_lvm_getextendedlistviewstyle : message_result -> listview_extended_style list = "unpack_lvm_getextendedlistviewstyle"
let issue_lvm_getextendedlistviewstyle ~sender = unpack_lvm_getextendedlistviewstyle (sender ~msg:pack_lvm_getextendedlistviewstyle)

let lvm_getheader = lvm_first + 31
let pack_lvm_getheader = pack_simple_message ~id:lvm_getheader
external unpack_lvm_getheader : message_result -> hwnd = "unpack_lvm_getheader"
let issue_lvm_getheader ~sender = unpack_lvm_getheader (sender ~msg:pack_lvm_getheader)

let lvm_gethotcursor = lvm_first + 63
let pack_lvm_gethotcursor = pack_simple_message ~id:lvm_gethotcursor
external unpack_lvm_gethotcursor : message_result -> hcursor = "unpack_lvm_gethotcursor"
let issue_lvm_gethotcursor ~sender = unpack_lvm_gethotcursor (sender ~msg:pack_lvm_gethotcursor)

let lvm_gethotitem = lvm_first + 61
let pack_lvm_gethotitem = pack_simple_message ~id:lvm_gethotitem
external unpack_lvm_gethotitem : message_result -> int = "unpack_lvm_gethotitem"
let issue_lvm_gethotitem ~sender = unpack_lvm_gethotitem (sender ~msg:pack_lvm_gethotitem)

let lvm_gethovertime = lvm_first + 72
let pack_lvm_gethovertime = pack_simple_message ~id:lvm_gethovertime
external unpack_lvm_gethovertime : message_result -> int = "unpack_lvm_gethovertime"
let issue_lvm_gethovertime ~sender = unpack_lvm_gethovertime (sender ~msg:pack_lvm_gethovertime)

let lvm_getimagelist = lvm_first + 2
external pack_lvm_getimagelist : which:listview_which_image_list -> message_contents = "pack_lvm_getimagelist"
external unpack_lvm_getimagelist : message_result -> himagelist = "unpack_lvm_getimagelist"
let issue_lvm_getimagelist ~sender ~which = unpack_lvm_getimagelist (sender ~msg:(pack_lvm_getimagelist ~which))

let lvm_getisearchstring = lvm_first + 52
external issue_lvm_getisearchstring : sender:message_sender -> string = "issue_lvm_getisearchstring"

let lvm_getitem = lvm_first + 5
external issue_lvm_getitem : sender:message_sender -> item:int -> sub_item:int -> mask:lvitem_component list -> lvitem = "issue_lvm_getitem"

let lvm_getitemcount = lvm_first + 4
let pack_lvm_getitemcount = pack_simple_message ~id:lvm_getitemcount
external unpack_lvm_getitemcount : message_result -> int = "unpack_lvm_getitemcount"
let issue_lvm_getitemcount ~sender = unpack_lvm_getitemcount (sender ~msg:pack_lvm_getitemcount)

let lvm_getitemposition = lvm_first + 16
external issue_lvm_getitemposition : sender:message_sender -> item:int -> point = "issue_lvm_getitemposition"

let lvm_getitemrect = lvm_first + 14
external issue_lvm_getitemrect : sender:message_sender -> item:int -> portion:listview_item_portion -> rect = "issue_lvm_getitemrect"

let lvm_getitemspacing = lvm_first + 51
external pack_lvm_getitemspacing : small:bool -> message_contents = "pack_lvm_getitemspacing"
external unpack_lvm_getitemspacing : message_result -> point = "unpack_lvm_getitemspacing"
let issue_lvm_getitemspacing ~sender ~small = unpack_lvm_getitemspacing (sender ~msg:(pack_lvm_getitemspacing ~small))

let lvm_getitemstate = lvm_first + 44
external issue_lvm_getitemstate : sender:message_sender -> item:int -> mask:lvitem_state_component list -> lvitem_state = "issue_lvm_getitemstate"

let lvm_getitemtext = lvm_first + 45
external issue_lvm_getitemtext : sender:message_sender -> item:int -> sub_item:int -> max_length:int -> string = "issue_lvm_getitemtext"

let lvm_getnextitem = lvm_first + 12
type listview_next_item_direction =
    LVNI_ALL
  | LVNI_ABOVE
  | LVNI_BELOW
  | LVNI_TOLEFT
  | LVNI_TORIGHT
type listview_next_item_state =
    LVNI_CUT
  | LVNI_DROPHILITED
  | LVNI_FOCUSED
  | LVNI_SELECTED
external pack_lvm_getnextitem :
    start:int ->
    direction:listview_next_item_direction ->
    state:listview_next_item_state list ->
    message_contents = "pack_lvm_getnextitem"
external unpack_lvm_getnextitem : message_result -> int option = "unpack_lvm_getnextitem"
let issue_lvm_getnextitem ~sender ~start ~direction ~state =
    unpack_lvm_getnextitem (sender ~msg:(pack_lvm_getnextitem ~start ~direction ~state))

let lvm_getnumberofworkareas = lvm_first + 73
external issue_lvm_getnumberofworkareas : sender:message_sender -> int = "issue_lvm_getnumberofworkareas"

let lvm_getorigin = lvm_first + 41
external issue_lvm_getorigin : sender:message_sender -> point = "issue_lvm_getorigin"

let lvm_getselectedcount = lvm_first + 50
let pack_lvm_getselectedcount = pack_simple_message ~id:lvm_getselectedcount
external unpack_lvm_getselectedcount : message_result -> int = "unpack_lvm_getselectedcount"
let issue_lvm_getselectedcount ~sender = unpack_lvm_getselectedcount (sender ~msg:pack_lvm_getselectedcount)

let lvm_getselectionmark = lvm_first + 66
let pack_lvm_getselectionmark = pack_simple_message ~id:lvm_getselectionmark
external unpack_lvm_getselectionmark : message_result -> int = "unpack_lvm_getselectionmark"
let issue_lvm_getselectionmark ~sender = unpack_lvm_getselectionmark (sender ~msg:pack_lvm_getselectionmark)

let lvm_getstringwidth = lvm_first + 17
external issue_lvm_getstringwidth : sender:message_sender -> str:string -> int = "issue_lvm_getstringwidth"

let lvm_getsubitemrect = lvm_first + 56
external issue_lvm_getsubitemrect :
    sender:message_sender ->
    item:int ->
    sub_item:int ->
    portion:listview_item_portion ->
    rect = "issue_lvm_getsubitemrect"

let lvm_gettextbkcolor = lvm_first + 37
let pack_lvm_gettextbkcolor = pack_simple_message ~id:lvm_gettextbkcolor
external unpack_lvm_gettextbkcolor : message_result -> color = "unpack_lvm_gettextbkcolor"
let issue_lvm_gettextbkcolor ~sender = unpack_lvm_gettextbkcolor (sender ~msg:pack_lvm_gettextbkcolor)

let lvm_gettextcolor = lvm_first + 35
let pack_lvm_gettextcolor = pack_simple_message ~id:lvm_gettextcolor
external unpack_lvm_gettextcolor : message_result -> color = "unpack_lvm_gettextcolor"
let issue_lvm_gettextcolor ~sender = unpack_lvm_gettextcolor (sender ~msg:pack_lvm_gettextcolor)

let lvm_gettooltips = lvm_first + 78
let pack_lvm_gettooltips = pack_simple_message ~id:lvm_gettooltips
external unpack_lvm_gettooltips : message_result -> hwnd = "unpack_lvm_gettooltips"
let issue_lvm_gettooltips ~sender = unpack_lvm_gettooltips (sender ~msg:pack_lvm_gettooltips)

let lvm_gettopindex = lvm_first + 39
let pack_lvm_gettopindex = pack_simple_message ~id:lvm_gettopindex
external unpack_lvm_gettopindex : message_result -> int = "unpack_lvm_gettopindex"
let issue_lvm_gettopindex ~sender = unpack_lvm_gettopindex (sender ~msg:pack_lvm_gettopindex)

(* lvm_getunicodeformat: use ccm_getunicodeformat *)

let lvm_getviewrect = lvm_first + 34
external issue_lvm_getviewrect : sender:message_sender -> rect = "issue_lvm_getviewrect"

let lvm_getworkareas = lvm_first + 70
external issue_lvm_getworkareas : sender:message_sender -> count:int -> rect list = "issue_lvm_getworkareas"

let lvm_hittest = lvm_first + 18
external issue_lvm_hittest : sender:message_sender -> pt:point -> listview_hit_test_result = "issue_lvm_hittest"

let lvm_insertcolumn = lvm_first + 27
external issue_lvm_insertcolumn : sender:message_sender -> col:int -> lvcolumn:lvcolumn -> int = "issue_lvm_insertcolumn"

let lvm_insertitem = lvm_first + 7
external issue_lvm_insertitem : sender:message_sender -> lvitem:lvitem -> int = "issue_lvm_insertitem"

let lvm_redrawitems = lvm_first + 21
external pack_lvm_redrawitems : first:int -> last:int -> message_contents = "pack_lvm_redrawitems"
external unpack_lvm_redrawitems : message_result -> unit = "unpack_lvm_redrawitems"
let issue_lvm_redrawitems ~sender ~first ~last = unpack_lvm_redrawitems (sender ~msg:(pack_lvm_redrawitems ~first ~last))

let lvm_scroll = lvm_first + 20
external pack_lvm_scroll : offset:point -> message_contents = "pack_lvm_scroll"
external unpack_lvm_scroll : message_result -> unit = "unpack_lvm_scroll"
let issue_lvm_scroll ~sender ~offset = unpack_lvm_scroll (sender ~msg:(pack_lvm_scroll ~offset))

let lvm_setbkcolor = lvm_first + 1
external pack_lvm_setbkcolor : color:color -> message_contents = "pack_lvm_setbkcolor"
external unpack_lvm_setbkcolor : message_result -> unit = "unpack_lvm_setbkcolor"
let issue_lvm_setbkcolor ~sender ~color = unpack_lvm_setbkcolor (sender ~msg:(pack_lvm_setbkcolor ~color))

let lvm_setbkimage = lvm_first + 68
external issue_lvm_setbkimage : sender:message_sender -> image:lvbkimage -> unit = "issue_lvm_setbkimage"

let lvm_setcallbackmask = lvm_first + 11
external pack_lvm_setcallbackmask : mask:lvitem_state_component list -> message_contents = "pack_lvm_setcallbackmask"
external unpack_lvm_setcallbackmask : message_result -> unit = "unpack_lvm_setcallbackmask"
let issue_lvm_setcallbackmask ~sender ~mask = unpack_lvm_setcallbackmask (sender ~msg:(pack_lvm_setcallbackmask ~mask))

let lvm_setcolumn = lvm_first + 26
external issue_lvm_setcolumn : sender:message_sender -> col:int -> lvcolumn:lvcolumn -> unit = "issue_lvm_setcolumn"

let lvm_setcolumnorderarray = lvm_first + 58
external issue_lvm_setcolumnorderarray : sender:message_sender -> order:int array -> unit = "issue_lvm_setcolumnorderarray"

let lvm_setcolumnwidth = lvm_first + 30
type listview_set_column_width =
    Lvscw_width of int
  | Lvscw_autosize
  | Lvscw_autosize_useheader
external pack_lvm_setcolumnwidth : col:int -> width:listview_set_column_width -> message_contents = "pack_lvm_setcolumnwidth"
external unpack_lvm_setcolumnwidth : message_result -> unit = "unpack_lvm_setcolumnwidth"
let issue_lvm_setcolumnwidth ~sender ~col ~width = unpack_lvm_setcolumnwidth (sender ~msg:(pack_lvm_setcolumnwidth ~col ~width))

let lvm_setextendedlistviewstyle = lvm_first + 54
external pack_lvm_setextendedlistviewstyle :
    mask:listview_extended_style list ->
    style:listview_extended_style list ->
    message_contents = "pack_lvm_setextendedlistviewstyle"
external unpack_lvm_setextendedlistviewstyle : message_result -> listview_extended_style list = "unpack_lvm_setextendedlistviewstyle"
let issue_lvm_setextendedlistviewstyle ~sender ~mask ~style = unpack_lvm_setextendedlistviewstyle (sender ~msg:(pack_lvm_setextendedlistviewstyle ~mask ~style))

let lvm_sethotcursor = lvm_first + 62
external pack_lvm_sethotcursor : cursor:hcursor -> message_contents = "pack_lvm_sethotcursor"
external unpack_lvm_sethotcursor : message_result -> hcursor = "unpack_lvm_sethotcursor"
let issue_lvm_sethotcursor ~sender ~cursor = unpack_lvm_sethotcursor (sender ~msg:(pack_lvm_sethotcursor ~cursor))

let lvm_sethotitem = lvm_first + 60
external pack_lvm_sethotitem : item:int -> message_contents = "pack_lvm_sethotitem"
external unpack_lvm_sethotitem : message_result -> int = "unpack_lvm_sethotitem"
let issue_lvm_sethotitem ~sender ~item = unpack_lvm_sethotitem (sender ~msg:(pack_lvm_sethotitem ~item))

let lvm_sethovertime = lvm_first + 71
external pack_lvm_sethovertime : time:int -> message_contents = "pack_lvm_sethovertime"
external unpack_lvm_sethovertime : message_result -> int = "unpack_lvm_sethovertime"
let issue_lvm_sethovertime ~sender ~time = unpack_lvm_sethovertime (sender ~msg:(pack_lvm_sethovertime ~time))

let lvm_seticonspacing = lvm_first + 53
external pack_lvm_seticonspacing : offset:point -> message_contents = "pack_lvm_seticonspacing"
external unpack_lvm_seticonspacing : message_result -> point = "unpack_lvm_seticonspacing"
let issue_lvm_seticonspacing ~sender ~offset = unpack_lvm_seticonspacing (sender ~msg:(pack_lvm_seticonspacing ~offset))

let lvm_setimagelist = lvm_first + 3
external pack_lvm_setimagelist : which:listview_which_image_list -> iml:himagelist -> message_contents = "pack_lvm_setimagelist"
external unpack_lvm_setimagelist : message_result -> himagelist = "unpack_lvm_setimagelist"
let issue_lvm_setimagelist ~sender ~which ~iml = unpack_lvm_setimagelist (sender ~msg:(pack_lvm_setimagelist ~which ~iml))

let lvm_setitem = lvm_first + 6
external issue_lvm_setitem : sender:message_sender -> lvitem:lvitem -> unit = "issue_lvm_setitem"

let lvm_setitemcount = lvm_first + 47
type listview_set_item_count_option =
    LVSICF_NOINVALIDATEALL
  | LVSICF_NOSCROLL
external pack_lvm_setitemcount : count:int -> options:listview_set_item_count_option list -> unit = "pack_lvm_setitemcount"
external unpack_lvm_setitemcount : message_result -> unit = "unpack_lvm_setitemcount"
let issue_lvm_setitemcount ~sender ~count ~options = unpack_lvm_setitemcount (sender ~msg:(pack_lvm_setitemcount ~count ~options))

let lvm_setitemposition = lvm_first + 15
external pack_lvm_setitemposition : item:int -> pos:point -> message_contents = "pack_lvm_setitemposition"
external unpack_lvm_setitemposition : message_result -> unit = "unpack_lvm_setitemposition"
let issue_lvm_setitemposition ~sender ~item ~pos = unpack_lvm_setitemposition (sender ~msg:(pack_lvm_setitemposition ~item ~pos))

let lvm_setitemposition32 = lvm_first + 49
external issue_lvm_setitemposition32 : sender:message_sender -> item:int -> pos:point -> unit = "issue_lvm_setitemposition32"

let lvm_setitemstate = lvm_first + 43
external issue_lvm_setitemstate : sender:message_sender -> item:int -> state:lvitem_state -> unit = "issue_lvm_setitemstate"

let lvm_setitemtext = lvm_first + 46
external issue_lvm_setitemtext :
    sender:message_sender ->
    item:int ->
    sub_item:int ->
    text:common_control_text ->
    unit = "issue_lvm_setitemtext"

let lvm_setselectionmark = lvm_first + 67
external pack_lvm_setselectionmark : mark:int -> message_contents = "pack_lvm_setselectionmark"
external unpack_lvm_setselectionmark : message_result -> int = "unpack_lvm_setselectionmark"
let issue_lvm_setselectionmark ~sender ~mark = unpack_lvm_setselectionmark (sender ~msg:(pack_lvm_setselectionmark ~mark))

let lvm_settextbkcolor = lvm_first + 38
external pack_lvm_settextbkcolor : color:color -> message_contents = "pack_lvm_settextbkcolor"
external unpack_lvm_settextbkcolor : message_result -> unit = "unpack_lvm_settextbkcolor"
let issue_lvm_settextbkcolor ~sender ~color = unpack_lvm_settextbkcolor (sender ~msg:(pack_lvm_settextbkcolor ~color))

let lvm_settextcolor = lvm_first + 36
external pack_lvm_settextcolor : color:color -> message_contents = "pack_lvm_settextcolor"
external unpack_lvm_settextcolor : message_result -> unit = "unpack_lvm_settextcolor"
let issue_lvm_settextcolor ~sender ~color = unpack_lvm_settextcolor (sender ~msg:(pack_lvm_settextcolor ~color))

let lvm_settooltips = lvm_first + 74
external pack_lvm_settooltips : tooltips:hwnd -> message_contents = "pack_lvm_settooltips"
external unpack_lvm_settooltips : message_result -> hwnd = "unpack_lvm_settooltips"
let issue_lvm_settooltips ~sender ~tooltips = unpack_lvm_settooltips (sender ~msg:(pack_lvm_settooltips ~tooltips))

(* lvm_setunicodeformat: use ccm_setunicodeformat *)

let lvm_setworkareas = lvm_first + 65
external issue_lvm_setworkareas : sender:message_sender -> areas:rect list -> unit = "issue_lvm_setworkareas"

let lvm_sortitems = lvm_first + 48
external issue_lvm_sortitems :
    sender:message_sender ->
    compare:(int32 -> int32 -> int) ->
    unit = "issue_lvm_sortitems"

let lvm_subitemhittest = lvm_first + 57
external issue_lvm_subitemhittest : sender:message_sender -> pt:point -> listview_hit_test_result = "issue_lvm_subitemhittest"

let lvm_update = lvm_first + 42
external pack_lvm_update : item:int -> message_contents = "pack_lvm_update"
external unpack_lvm_update : message_result -> unit = "unpack_lvm_update"
let issue_lvm_update ~sender ~item = unpack_lvm_update (sender ~msg:(pack_lvm_update ~item))

(* Notifications *)

type nmlvcustomdraw = {
    nmlvcd_item_spec : int;
    nmlvcd_text_color : color;
    nmlvcd_text_bk_color : color;
    nmlvcd_sub_item : int }
external unpack_nmlvcustomdraw : msg:message_contents -> nmlvcustomdraw = "unpack_nmlvcustomdraw"

type nmlistview = {
    nmlv_item : int;
    nmlv_sub_item : int;
    nmlv_new_state : lvitem_state;
    nmlv_old_state : lvitem_state;
    nmlv_changed : lvitem_component list;
    nmlv_point : point;
    nmlv_lparam : int32 }
external unpack_nmlistview : msg:message_contents -> nmlistview = "unpack_nmlistview"

type nmlvdispinfo = {
    nmlvdi_item : lvitem }
external unpack_nmlvdispinfo : msg:message_contents -> nmlvdispinfo = "unpack_nmlvdispinfo"

type listview_modifier_key =
    LVKF_ALT
  | LVKF_CONTROL
  | LVKF_SHIFT
type nmitemactivate = {
    nmia_item : int;
    nmia_sub_item : int;
    nmia_new_state : lvitem_state;
    nmia_old_state : lvitem_state;
    nmia_changed : lvitem_component list;
    nmia_point : point;
    nmia_lparam : int32;
    nmia_key_flags : listview_modifier_key list }
external unpack_nmitemactivate : msg:message_contents -> nmitemactivate = "unpack_nmitemactivate"

type nmlvkeydown = {
    nmlvkd_key : virtual_key_code }
external unpack_nmlvkeydown : msg:message_contents -> nmlvkeydown = "unpack_nmlvkeydown"

type nmlvcachehint = {
    nmlvch_from : int;
    nmlvch_to : int }
external unpack_nmlvcachehint : msg:message_contents -> nmlvcachehint = "unpack_nmlvcachehint"

type nmlvfinditem = {
    nmlvfi_info : lvfindinfo }
external unpack_nmlvfinditem : msg:message_contents -> nmlvfinditem = "unpack_nmlvfinditem"

type nmlvodstatechange = {
    nmlvsc_from : int;
    nmlvsc_to : int;
    nmlvsc_new_state : lvitem_state;
    nmlvsc_old_state : lvitem_state }
external unpack_nmlvodstatechange : msg:message_contents -> nmlvodstatechange = "unpack_nmlvodstatechange"

let lvn_first = -100
let lvn_last = -199

let lvn_begindrag = lvn_first - 9
let on_lvn_begindrag = on_notify_message ~code:lvn_begindrag ~unpack:unpack_nmlistview ~return:return_simple_message

let lvn_beginlabeledit = lvn_first - 5
let on_lvn_beginlabeledit = on_notify_message ~code:lvn_beginlabeledit ~unpack:unpack_nmlvdispinfo ~return:return_common_notify

let lvn_beginrdrag = lvn_first - 11
let on_lvn_beginrdrag = on_notify_message ~code:lvn_beginrdrag ~unpack:unpack_nmlistview ~return:return_simple_message

let lvn_columnclick = lvn_first - 8
let on_lvn_columnclick = on_notify_message ~code:lvn_columnclick ~unpack:unpack_nmlistview ~return:return_simple_message

let lvn_deleteallitems = lvn_first - 4
let on_lvn_deleteallitems = on_notify_message ~code:lvn_deleteallitems ~unpack:unpack_nmlistview ~return:return_common_notify

let lvn_deleteitem = lvn_first - 3
let on_lvn_deleteitem = on_notify_message ~code:lvn_deleteitem ~unpack:unpack_nmlistview ~return:return_simple_message

let lvn_endlabeledit = lvn_first - 6
external return_lvn_endlabeledit : result:bool -> message_result = "return_lvn_endlabeledit"
let on_lvn_endlabeledit = on_notify_message ~code:lvn_endlabeledit ~unpack:unpack_nmlvdispinfo ~return:return_lvn_endlabeledit

let lvn_getdispinfo = lvn_first - 50
type lvn_getdispinfo_handler =
    wnd:hwnd ->
    msg:message_contents ->
    id:int ->
    hdr:nmhdr ->
    item:int ->
    sub_item:int ->
    mask:lvitem_component list ->
    (lvitem * bool) message_handler_result
external on_lvn_getdispinfo :
    lvn_getdispinfo_handler ->
    wnd:hwnd ->
    msg:message_contents ->
    message_result option = "on_lvn_getdispinfo"

let lvn_getinfotip = lvn_first - 57
(* ... *)

let lvn_insertitem = lvn_first - 2
let on_lvn_insertitem = on_notify_message ~code:lvn_insertitem ~unpack:unpack_nmlistview ~return:return_simple_message

let lvn_hottrack = lvn_first - 21
type lvn_hottrack_result =
    Lvnhtr_normal
  | Lvnhtr_none
  | Lvnhtr_other of int
external on_lvn_hottrack :
    (nmlistview, lvn_hottrack_result) notify_message_handler ->
    wnd:hwnd ->
    msg:message_contents ->
    message_result option = "on_lvn_hottrack"

let lvn_itemactivate = lvn_first - 14
let on_lvn_itemactivate = on_notify_message ~code:lvn_itemactivate ~unpack:unpack_simple_notify ~return:return_simple_message
let on_lvn_itemactivate_ex = on_notify_message ~code:lvn_itemactivate ~unpack:unpack_nmitemactivate ~return:return_simple_message

let lvn_itemchanged = lvn_first - 1
let on_lvn_itemchanged = on_notify_message ~code:lvn_itemchanged ~unpack:unpack_nmlistview ~return:return_simple_message

let lvn_itemchanging = lvn_first - 0
let on_lvn_itemchanging = on_notify_message ~code:lvn_itemchanging ~unpack:unpack_nmlistview ~return:return_common_notify

let lvn_keydown = lvn_first - 55
let on_lvn_keydown = on_notify_message ~code:lvn_keydown ~unpack:unpack_nmlvkeydown ~return:return_simple_message

let lvn_marqueebegin = lvn_first - 56
let on_lvn_marqueebegin = on_notify_message ~code:lvn_marqueebegin ~unpack:unpack_nmlistview ~return:return_common_notify

let lvn_odcachehint = lvn_first - 13
let on_lvn_odcachehint = on_notify_message ~code:lvn_odcachehint ~unpack:unpack_nmlvcachehint ~return:return_simple_message

let lvn_odfinditem = lvn_first - 52
external return_lvn_odfinditem : result:int option -> message_result = "return_lvn_odfinditem"
let on_lvn_odfinditem = on_notify_message ~code:lvn_odfinditem ~unpack:unpack_nmlvfinditem ~return:return_lvn_odfinditem

let lvn_odstatechanged = lvn_first - 15
let on_lvn_odstatechanged = on_notify_message ~code:lvn_odstatechanged ~unpack:unpack_nmlvodstatechange ~return:return_simple_message

let lvn_setdispinfo = lvn_first - 51
let on_lvn_setdispinfo = on_notify_message ~code:lvn_setdispinfo ~unpack:unpack_nmlvdispinfo ~return:return_simple_message
