#[macro_use]
extern crate lazy_static;
extern crate winapi;
use winapi::shared::windowsx as winx;
use winapi::um::{minwinbase::LMEM_MOVEABLE, winnt::{LPCWSTR, LONG, HANDLE}};
use winapi::um::{shellapi as shell, winuser as user, wingdi as gdi, winbase as win};
use winapi::shared::windef::{HWND, HMENU, HBRUSH, HICON, HFONT, HGDIOBJ, HBITMAP, HDC, RECT, POINT};
use winapi::shared::minwindef::{INT, UINT, DWORD, MAX_PATH, HINSTANCE, HGLOBAL, LRESULT, LPVOID, WPARAM, LPARAM, HIWORD, LOWORD};
use user::{WS_OVERLAPPEDWINDOW, WS_VISIBLE, WS_CHILD, WS_BORDER, WS_SYSMENU, WS_POPUP, WS_CAPTION, WNDCLASSEXW, WNDPROC, LPCREATESTRUCTW};
use std::{ptr, mem, io::{Read, Write}, fs::File, ffi::OsStr, sync::Mutex, string::String, os::windows::ffi::OsStrExt};
const SX: i32 = 200; const SY: i32 = 200; const W: i32 = 800; const H: i32 = 600;
const R_A: u8 = 250; const G_A: u8 = 250; const B_A: u8 = 250;
const R_B: u8 = 0; const G_B: u8 = 0; const B_B: u8 = 0;
const R_C: u8 = 100; const G_C: u8 = 100; const B_C: u8 = 100;
const NEWLINE :char = '\n'; const NOTLINE :char = '\r';
struct SA {s :usize, e :usize}
struct CH {x :LONG, y :LONG, c :char}
struct MV {font :HFONT, save: HICON, edit :HICON, visual :HICON, sw :HWND}
lazy_static!
{
static ref MODE: Mutex<u8> = Mutex::new(0);
static ref TEXT: Mutex<Vec<CH>> = Mutex::new(Vec::new());
static ref POS: Mutex<POINT> = Mutex::new(POINT{x:0, y:0});
static ref CHX: Mutex<LONG> = Mutex::new(0);
static ref CHY: Mutex<LONG> = Mutex::new(0);
static ref DEY: Mutex<LONG> = Mutex::new(0);
static ref END: Mutex<u8> = Mutex::new(0);
static ref KEY: Mutex<u32> = Mutex::new(0);
static ref STATE: Mutex<u32> = Mutex::new(0);
static ref SCREEN: Mutex<LONG> = Mutex::new(31);
static ref REGION: Mutex<SA> = Mutex::new(SA{s:0, e:0});
static ref BUFFER: Mutex<String> = Mutex::new(String::new());
static ref RBUFFER: Mutex<String> = Mutex::new(String::new());
}
fn to_wstring(str : &str) -> Vec<u16>
{
return OsStr::new(str).encode_wide().chain(Some(0).into_iter()).collect();
}
fn copy(w :HWND, f :HFONT)
{
unsafe
{
let region = {REGION.lock().unwrap()};
if region.s != region.e
{
let mut buffer = String::new();
setbuffer(region.s, region.e, &mut buffer);
user::OpenClipboard(ptr::null_mut());
user::EmptyClipboard();
let hg :HGLOBAL = win::GlobalAlloc(LMEM_MOVEABLE, region.e - region.s);
if hg == ptr::null_mut()
{
user::CloseClipboard();
return;
}
ptr::copy_nonoverlapping(buffer.as_ptr(), win::GlobalLock(hg) as *mut u8, region.e - region.s);
win::GlobalUnlock(hg);
user::SetClipboardData(user::CF_TEXT, hg);
user::CloseClipboard();
win::GlobalFree(hg);
}
}
}
fn paste(w :HWND, f :HFONT)
{
unsafe
{
user::OpenClipboard(ptr::null_mut());
let handle :HANDLE = user::GetClipboardData(user::CF_TEXT);
let ptr = win::GlobalLock(handle) as *mut u8;
let length = strlength(ptr);
let data = std::slice::from_raw_parts(ptr, length);
let buffer : String = String::from_utf8_lossy(data).to_string();
win::GlobalUnlock(handle);
user::CloseClipboard();
draw(w, f, buffer);
}
}
fn file(w :HWND, f :HFONT, path :String, mode :u8)
{
let result = File::open(path);
match result
{
Ok(mut result) =>
{
match mode
{
0 =>
{
hidecaret(w);
clear();
clearscreen(w);
*POS.lock().unwrap() = POINT{x:0, y:0};
let mut buffer = String::new();
result.read_to_string(&mut buffer);
draw(w, f, buffer);
showcaret(w);
*END.lock().unwrap() = 1;
},
_ =>
{
},
}
},
_ =>
{
println!("file error");
},
}
}
fn clear() {let mut vec = {TEXT.lock().unwrap()}; vec.clear();}
fn remove(i :usize){let mut vec = {TEXT.lock().unwrap()}; vec.remove(i);}
fn insert(i :usize, c :CH){let mut vec = {TEXT.lock().unwrap()}; vec.insert(i, c)}
fn save(c :CH){let mut vec = {TEXT.lock().unwrap()}; vec.push(c);}
fn getlength() -> usize {let vec = {TEXT.lock().unwrap()}; let length = vec.len();length}
fn getx(i :usize) -> LONG {let vec = {TEXT.lock().unwrap()}; let x = vec[i].x; x}
fn gety(i :usize) -> LONG {let vec = {TEXT.lock().unwrap()}; let y = vec[i].y; y}
fn getc(i :usize) -> char {let vec = {TEXT.lock().unwrap()}; let c = vec[i].c; c}
fn setx(i :usize, x :LONG){let mut vec = {TEXT.lock().unwrap()}; vec[i].x = x;}
fn sety(i :usize, y :LONG){let mut vec = {TEXT.lock().unwrap()}; vec[i].y = y;}
fn getprevlastx() -> usize
{
let y = {POS.lock().unwrap().y};
if y == 0 {return 0;}
let py = y - 1;
let vec = {TEXT.lock().unwrap()};
let index = vec.iter().position(|ref e| ((e.c == NEWLINE) && (e.y == py)));
match index { None => {return 0}, _ => {return index.unwrap()}}
}
fn getlastx() -> usize
{
let y = {POS.lock().unwrap().y};
let vec = {TEXT.lock().unwrap()};
let index = vec.iter().position(|ref e| ((e.c == NEWLINE) && (e.y == y)));
match index {None => {return vec.len()-1}, _ => {return index.unwrap()}}
}
fn getlastpos() -> POINT
{
let vec = {TEXT.lock().unwrap()};
let len = vec.len();
match len
{
0 => {return POINT{x:0, y:0};},
_ =>
{
match vec[len-1].c
{
NEWLINE => return POINT{x:0, y:vec[len-1].y+1},
_ => return POINT{x:vec[len-1].x+1, y:vec[len-1].y},
}
},
}
}
fn findmore() -> i32
{
let x = {POS.lock().unwrap().x};
let y = {POS.lock().unwrap().y};
let vec = {TEXT.lock().unwrap()};
let mut max :i32 = -1;
for v in vec.iter() {if (v.y == y) && (v.x > max) {max = v.x;}}
if (max+1) > x {return max+1;}
return 0;
}
fn getindex() -> Option<usize>
{
let x = {POS.lock().unwrap().x};
let y = {POS.lock().unwrap().y};
let vec = {TEXT.lock().unwrap()};
return vec.iter().position(|ref e| ((e.x == x) && (e.y == y)));
}
fn getchar(x :i32, y :i32) -> Option<char>
{
let vec = {TEXT.lock().unwrap()};
let index = vec.iter().position(|ref e| ((e.x == x) && (e.y == y)));
match index
{
None => {return None;}, _ => {return Some(vec[index.unwrap()].c);},
}
}
fn strlength(buffer :*mut u8) -> usize
{
unsafe
{
let mut i : isize = 0;
while *buffer.offset(i) != 0 {i+=1;}
i as usize
}
}
fn setrbuffer(s :usize, e :usize, rstring :&mut String)
{
let mut vec = {TEXT.lock().unwrap()};
for i in s..(e+1){rstring.push(vec.pop().unwrap().c)}
}
fn setbuffer(s :usize, e :usize, string :&mut String)
{
let vec = {TEXT.lock().unwrap()};
vec[s..=e].iter().for_each(|ref x| string.push(x.c));
}
fn removeline(start :usize, end :usize)
{
let mut vec = {TEXT.lock().unwrap()};
for i in start..end{vec.remove(start);}
for i in start..vec.len() {vec[i].y -= 1;}
}
fn window(c :Vec<u16>, win :Vec<u16>, proc :WNDPROC, icon :HICON, style :DWORD, w :i32, h :i32, v :LPVOID) -> HWND
{
unsafe
{
let wnd = WNDCLASSEXW
{
cbSize: mem::size_of::<WNDCLASSEXW>() as u32,
style: 0, lpfnWndProc: proc, cbClsExtra: 0, cbWndExtra: 0,
hInstance: 0 as HINSTANCE, hIcon: icon as HICON,
hCursor: 0 as HICON, hbrBackground: 0 as HBRUSH, lpszMenuName: 0 as LPCWSTR,
lpszClassName: c.as_ptr(), hIconSm: icon as HICON,
};
user::RegisterClassExW(&wnd);
return user::CreateWindowExW(0, c.as_ptr(), win.as_ptr(),
style, 0, 0, w, h, 0 as HWND, 0 as HMENU, 0 as HINSTANCE, v);
}
}
fn change_state(w :HWND, icon :HICON)
{
unsafe{user::SendMessageW(w, user::WM_SETICON, user::ICON_SMALL as usize, icon as LPARAM);}
}
fn clearscreen(w :HWND)
{
unsafe
{
user::InvalidateRect(w, ptr::null_mut(), 1);
user::RedrawWindow(w, ptr::null_mut(), ptr::null_mut(), user::RDW_INVALIDATE | user::RDW_UPDATENOW);
}
}
fn clearch(w :HWND, i :usize, r :i32)
{
let rect = getrect(i);
unsafe {user::InvalidateRect(w, &rect, r);}
}
fn clearrange(w :HWND, f :HFONT, start :usize, end :usize)
{
for i in start..(end+1){drawtext(w, f, &CH{x:getx(i),y:gety(i),c:' '}, 1, 0);}
}
fn drawrange(w :HWND, f :HFONT, start :usize, end :usize)
{
for i in start..(end+1){drawtext(w, f, &CH{x:getx(i),y:gety(i),c:getc(i)}, 1, 0);}
}
fn getrect(i :usize) -> RECT
{
let v = {TEXT.lock().unwrap()};
let w = {*CHX.lock().unwrap()};
let h = {*CHY.lock().unwrap()};
let r = RECT{left:v[i].x*w,top:(v[i].y*h),right:(v[i].x*w+w),bottom:(v[i].y*h+h)};
r
}
fn decpos(x :i32, y: i32, lastx :i32)
{
if x > 0
{
POS.lock().unwrap().x -= 1;
}
else if y > 0
{
POS.lock().unwrap().y -= 1;
POS.lock().unwrap().x = lastx;
}
}
fn getpos(x :i32, y:i32) -> Option<POINT>
{
let vec = {TEXT.lock().unwrap()};
let w = {*CHX.lock().unwrap()};
let h = {*CHY.lock().unwrap()};
for v in vec.iter()
{
if ((v.y*h <= y) && (v.y*h+h > y)) &&
((v.x*w <= x) && (v.x*w+w > x)) {return Some(POINT{x:v.x, y:v.y});}
}
return None;
}
fn setposx(x :i32){POS.lock().unwrap().x = x;} fn setposy(y :i32){POS.lock().unwrap().y = y;}
fn setposmx(x :i32){POS.lock().unwrap().x -= x;} fn setpospx(x :i32){POS.lock().unwrap().x += x;}
fn setposmy(y :i32){POS.lock().unwrap().y -= y;} fn setpospy(y :i32){POS.lock().unwrap().y += y;}
fn getposx() -> i32 {POS.lock().unwrap().x} fn getposy() -> i32 {POS.lock().unwrap().y}
fn getw() -> i32 {*CHX.lock().unwrap()} fn geth() -> i32 {*CHY.lock().unwrap()}
fn setmode(mode :u8){*MODE.lock().unwrap() = mode} fn getmode() -> u8 {*MODE.lock().unwrap()}
fn setstate(state :u32, mode :u8)
{
match mode {0 => {*STATE.lock().unwrap() |= state}, _ => {*STATE.lock().unwrap() &= state}}
}
fn getstate() -> u32 {*STATE.lock().unwrap()}
fn setregion(pos :usize, mode :u8)
{
let start = {REGION.lock().unwrap().s};
match mode
{
0 => {REGION.lock().unwrap().s = pos;},
_ =>
{
match start > pos
{
true => {REGION.lock().unwrap().s = pos; REGION.lock().unwrap().e = start; }
_ => {REGION.lock().unwrap().e = pos;},
}
},
}
}
fn clickpos(x :i32, y: i32)
{
let vec = {TEXT.lock().unwrap()};
let w = getw();
let h = geth();
for v in vec.iter()
{
if ((v.y*h <= y) && (v.y*h+h > y)) &&
((v.x*w <= x) && (v.x*w+w > x)) {setposx(v.x);setposy(v.y);break;}
}
}
fn delete(w :HWND, f :HFONT)
{
let x = getposx();
let y = getposy();
if x == 0 && y == 0 {return;}
let mut line_end :usize = 0;
let size = getlength()-1;
let lastx = getlastx();
match lastx
{
size =>
{
if y == 0
{
hidecaret(w);
let max = findmore() as usize;
setposmx(1);
if max > 0
{
let x = getposx() as usize;
for i in x..max
{
clearch(w, i, 0);
setx(i, getx(i)-1);
}
remove(x);
let end = max-1;
for i in x..end
{
let ch = CH{x:getx(i),y:gety(i),c:getc(i)};
drawtext(w, f, &ch, 1, 0);
}
let ch = CH{x:end as i32,y:0,c:' '};
drawtext(w, f, &ch, 1, 0);
}
else
{
let x = getposx() as usize;
clearch(w, x, 1);
remove(x);
}
showcaret(w);
return;
}
else
{
hidecaret(w);
let px = getprevlastx();
let i = px + x as usize;
clearch(w, i, 1);
decpos(x, y, px as i32);
showcaret(w);
remove(i);
return;
}
},
_ =>
{
line_end = lastx;
},
}
decpos(x, y, getx(line_end));
let index = getindex();
match index
{
None =>
{
println!("no index");
},
_ =>
{
hidecaret(w);
let index = index.unwrap();
for i in index..(line_end+1)
{
clearch(w, i, 0);
setx(i, getx(i)-1);
}
remove(index);
let end = line_end-1;
for i in index..end
{
let ch = CH{x:getx(i),y:gety(i),c:getc(i)};
drawtext(w, f, &ch, 1, 0);
}
let ch = CH{x:getx(end),y:gety(end),c:' '};
drawtext(w, f, &ch, 1, 0);
showcaret(w);
},
}
}
fn enter(w :HWND, f :HFONT){save(CH{x:getposx(),y:getposy(),c:NEWLINE});}
fn draw(w :HWND, f :HFONT, buffer :String)
{
for c in buffer.chars()
{
let x = getposx();
let y = getposy();
match c
{
NEWLINE => {save(CH{x:x, y:y,c:c}); setposx(0); setpospy(1);},
NOTLINE => {},
_ =>
{
let ch = CH{x:x,y:y,c:c};
let screen = {*SCREEN.lock().unwrap()};
if y < screen {drawtext(w, f, &ch, 0, 0);}
save(ch);
setpospx(1);
},
}
}
}
fn copy2(w :HWND, f :HFONT, mode :u8)
{
let mut buffer = {BUFFER.lock().unwrap()};
let region = {REGION.lock().unwrap()};
if region.s != region.e
{
setbuffer(region.s, region.e, &mut buffer);
match mode { 0 =>(), _ => {redraw(w, f, 0, 1, region.s, region.e); }}
}
}
fn redraw(w :HWND, f :HFONT, offset: isize, mode :u8, s :usize, e :usize)
{
match mode
{
1 =>
{
if s != e {
let vec = {TEXT.lock().unwrap()};
vec[s..=e].iter().for_each(|ref x| drawtext(w, f, &x, 0, 0));
}
},
_ =>
{
clearscreen(w);
let vec = {TEXT.lock().unwrap()};
vec.iter().for_each(|ref x| drawtext(w, f, &x, 2, offset));
}
}
}
fn drawtext(w :HWND, f :HFONT, c :&CH, p :WPARAM, l :LPARAM)
{
unsafe
{
let dc = user::GetDC(w) as HDC;
gdi::SelectObject(dc, f as HGDIOBJ);
gdi::SetTextColor(dc, gdi::RGB(R_A,G_A,B_A));
let string :String = c.c.to_string();
let ch = to_wstring(&string);
let ch_w = getw();
let ch_h = geth();
match p
{
2 =>
{
let y = c.y + l as i32;
gdi::SetBkColor(dc, gdi::RGB(R_B,G_B,B_B));
gdi::TextOutW(dc, c.x * ch_w, y * ch_h, ch.as_ptr(), 1);
},
_ =>
{
match l
{
1 => {gdi::SetBkColor(dc, gdi::RGB(R_C,G_C,B_C));},
_ => {gdi::SetBkColor(dc, gdi::RGB(R_B,G_B,B_B));},
}
gdi::TextOutW(dc, c.x * ch_w, c.y * ch_h, ch.as_ptr(), 1);
},
}
user::ReleaseDC(w, dc);
}
}
fn key_up(w :HWND){let y = getposy();if y == 0 {return;} hidecaret(w);setposmy(1); showcaret(w);}
fn key_down(w :HWND){hidecaret(w);setpospy(1);showcaret(w);}
fn key_left(w :HWND)
{
let state = getstate();
let x = getposx() as usize;
if x == 0 {return;}
*END.lock().unwrap() = 0;
setposmx(1);
let index = getindex();
match index
{
None => {}, _ => {hidecaret(w);setposx(getx(index.unwrap()));showcaret(w);},
}
}
fn key_right(w :HWND, f :HFONT)
{
let index = getindex();
match index
{
None => (),
_ =>
{
let state = getstate();
let i = index.unwrap();
if NEWLINE == getc(i) {return;}
let length = getlength();
let end = {*END.lock().unwrap()};
if (length - 1) == i
{
if end != 1
{
*END.lock().unwrap() = 1;
hidecaret(w);
setposx(getx(i)+1);
if state == 0x88 {drawtext(w, f, &CH{x:getx(i),y:gety(i),c:getc(i)}, 1, 1);}
showcaret(w);
}
return;
}
hidecaret(w);
if state == 0x88 {drawtext(w, f, &CH{x:getx(i),y:gety(i),c:getc(i)}, 1, 1);}
setposx(getx(i+1));
showcaret(w);
},
}
}
fn showcaret(w :HWND)
{
unsafe
{
let index = getindex();
match index
{
None =>
{
let len = getlength();
match len
{
0 => {user::SetCaretPos(0,0); user::ShowCaret(w);},
_ =>
{
user::SetCaretPos(getposx()*getw(), getposy()*geth());
user::ShowCaret(w);
},
}
},
_ =>
{
let i = index.unwrap();
user::SetCaretPos(getx(i)*getw(), gety(i)*geth());
user::ShowCaret(w);
},
}
}
}
fn hidecaret(w :HWND) {unsafe{user::HideCaret(w);}}
fn wheel_up(w :HWND, f :HFONT)
{
let delta = {*DEY.lock().unwrap()} as isize;
if delta == 0 {return};
clearscreen(w);
*DEY.lock().unwrap() += 2;
let delta = {*DEY.lock().unwrap()} as isize;
let vec = {TEXT.lock().unwrap()};
for val in vec.iter()
{
match val.c
{
NEWLINE => {setposx(0);setpospy(1);},
NOTLINE => {},
_ =>{drawtext(w, f, val, 2, delta);},
}
}
}
fn wheel_down(w :HWND, f :HFONT)
{
clearscreen(w);
*DEY.lock().unwrap() -= 2;
let delta = {*DEY.lock().unwrap()} as isize;
let vec = {TEXT.lock().unwrap()};
for val in vec.iter()
{
match val.c
{
NEWLINE => {setposx(0);setpospy(1);},
NOTLINE => {},
_ =>{drawtext(w, f, val, 2, delta);},
}
}
}
fn ctrl(w :HWND, p :WPARAM, mov :&mut MV)
{
let f = mov.font;
let sw = mov.sw;
match p
{
0x08 => {
let path = String::from("./help.txt");
file(w, f, path, 0);
},
0x0F => {
let length = getlength();
println!("debug, length: {0}", length);
let vec = {TEXT.lock().unwrap()};
for val in vec.iter() {print!("[{0:02x},{1},{2}]", val.c as u8, val.x, val.y);} println!{""};
},
0x18 => {
let path = String::from("./test.txt");
file(w, f, path, 0);
},
0x13 => println!("0x13"),
0x02 => {
clear();
clearscreen(w);
hidecaret(w);
setposx(0);
setposy(0);
showcaret(w);
},
0x03 => copy(w, f), 0x16 => paste(w, f), 0x17 => sidepanel(w, sw, f), _ => (),
}
}
fn key_0x24() {
let index = getindex();
match index
{
None => {},
_ =>
{
let index = index.unwrap();
let length = getlength();
let y = getposy();
let w = getw() as i32;
let h = geth();
for i in index..length
{
if getc(i) == NEWLINE
{
let x = getx(i);
unsafe{user::SetCaretPos(x*w, y*h);}
setposx(x);
break;
}
else if i == (length-1)
{
*END.lock().unwrap() = 1;
let x = getx(i)+1;
unsafe{user::SetCaretPos(x*w, y*h);}
setposx(x);
}
}
},
}
}
fn key_0x30() {
*END.lock().unwrap() = 0;
let y = getposy();
let ch_h = {*CHY.lock().unwrap()};
unsafe{user::SetCaretPos(0, y*ch_h);}
setposx(0);
}
fn key_0x44(w :HWND) {
hidecaret(w);
showcaret(w);
}
fn key_0x47(w :HWND) {
hidecaret(w); let p = getlastpos(); setposx(p.x); setposy(p.y); showcaret(w);
}
fn key_0x64(w :HWND, f :HFONT) {
let state = getstate();
let key = {*KEY.lock().unwrap()};
match key
{
0 =>
{
*KEY.lock().unwrap() = 0x164;
},
0x164 =>
{
*KEY.lock().unwrap() = 0;
hidecaret(w);
let mut start :usize = 0;
let mut end :usize = 0;
end = getlastx();
start = getprevlastx() + 1;
clearrange(w, f, start, end);
removeline(start, end+1);
end = getlength();
removeline(start, end);
setposx(0);
showcaret(w);
},
_ =>
{
*KEY.lock().unwrap() = 0;
},
}
}
fn key_0x67(w :HWND) {
let key = {*KEY.lock().unwrap()};
match key
{
0 => {*KEY.lock().unwrap() = 0x167;},
0x167 =>
{
*KEY.lock().unwrap() = 0;
hidecaret(w);
setposx(0);
setposy(0);
showcaret(w);
},
_ => {*KEY.lock().unwrap() = 0;},
}
}
fn key_0x6f(w :HWND, f :HFONT, icon :HICON) {
setmode(3); change_state(w, icon); enter(w,f); hidecaret(w); setposx(0); setpospy(1); showcaret(w);
}
fn key_0x70(w :HWND, f :HFONT) {
let mut buffer = {BUFFER.lock().unwrap()};
let len = buffer.len();
println!("key_0x70: debug, length: {0}", len);
let index = getindex();
match index
{
None => (),
_ =>
{
let lastx = getlastx();
let i = index.unwrap();
println!("key_0x70: debug, i: {0}, end: {1}", i, lastx);
clearrange(w, f, i, lastx);
for val in 0..len
{
let x = getposx();
let y = getposy();
let c = buffer.pop().unwrap();
insert(i, CH{x:x, y:y, c:c});
setpospx(1);
}
let lastx = getlastx();
println!("key_0x70: debug, i: {0}, end: {1}", i, lastx);
drawrange(w, f, i, lastx);
}
}
}
fn key_0x79(w :HWND, f :HFONT, icon :HICON) {
let state = getstate();
match state & 0x88
{
0x88 =>
{
setstate(0xFFFFFF77, 1); change_state(w, icon);
setmode(0);
let index = getindex();
match index { None => (), _ => {setregion(index.unwrap()-1, 1); } }
copy2(w, f, 1);
},
_ => (),
}
}
fn key_0x1B(w :HWND, f :HFONT, icon :HICON) {
match getmode()
{
0 => (),
_ =>
{
setmode(0);
change_state(w, icon);
let state = getstate();
match state & 0x88
{
0x88 =>
{
setstate(0xFFFFFF77, 1);
let index = getindex();
match index { None => (), _ => {setregion(index.unwrap()-1, 1);} }
let region = {REGION.lock().unwrap()};
if region.s != region.e {redraw(w, f, 0, 1, region.s, region.e);}
},
_ => (),
}
}
}
}
fn key_0x0D(w :HWND, f :HFONT) {
enter(w, f); hidecaret(w); setposx(0);setpospy(1); showcaret(w);
}
fn key_input(w :HWND, f :HFONT, p :WPARAM) {
let x = getposx();
let y = getposy();
let index = getindex();
let c = unsafe{std::char::from_u32_unchecked(p as u32)};
match index
{
None =>
{
hidecaret(w);
let ch = CH{x:x as i32,y:y as i32,c:c};
drawtext(w, f, &ch, 0, 0);
save(ch);
setpospx(1);
showcaret(w);
},
_ =>
{
let index = index.unwrap();
let length = getlength();
if index < length
{
let mut line_end = length+1;
hidecaret(w);
for i in index..length
{
let c = getc(i);
if NEWLINE == c
{
line_end = i+1;
setx(i, getx(i)+1);
break;
}
else
{
clearch(w, i, 0);
setx(i, getx(i)+1);
}
}
let ch = CH{x:x as i32,y:y as i32,c:c};
insert(index, ch);
for i in index..line_end
{
let ch = CH{x:getx(i) as i32,y:gety(i) as i32,c:getc(i)};
drawtext(w, f, &ch, 1, 0);
}
setpospx(1);
showcaret(w);
}
else
{
println!("index >= length");
}
},
}
}
fn edit(w :HWND, p :WPARAM, mov :&mut MV)
{
unsafe
{
let f = mov.font;
let icon = mov.save;
let icon2 = mov.edit;
let icon3 = mov.visual;
let mode = getmode();
match mode
{
0 =>
{
hidecaret(w);
match p
{
0x24 => key_0x24(), 0x30 => key_0x30(), 0x44 => key_0x44(w), 0x47 => key_0x47(w), 0x61 => {setmode(1); change_state(w, icon2);}, 0x64 => key_0x64(w,f), 0x67 => key_0x67(w), 0x69 => {setmode(2); change_state(w, icon2);}, 0x6f => key_0x6f(w,f,icon2), 0x70 => key_0x70(w, f), 0x76 => {setmode(4); change_state(w, icon3);}, 0x7A => println!("0x7A"),
0x68 => key_left(w), 0x6A => key_down(w), 0x6B => key_up(w), 0x6C => key_right(w, f),
_ => (),
}
user::ShowCaret(w);
return;
},
4 =>
{
match getstate() & 0x88
{
0x88 => (),
_ =>
{
setstate(0x88, 0); let index = getindex();
match index { None => (), _ => {setregion(index.unwrap(), 0); } }
}
}
hidecaret(w);
match p
{
0x79 => key_0x79(w, f, icon), 0x1B => key_0x1B(w, f, icon),
0x68 => key_left(w), 0x6A => key_down(w), 0x6B => key_up(w), 0x6C => key_right(w, f),
_ => (),
}
user::ShowCaret(w);
return;
},
_ => (),
}
match p
{
0x08 => delete(w,f), 0x0D => key_0x0D(w,f), 0x1B => key_0x1B(w, f, icon), _ => key_input(w,f,p), }
}
}
fn sidepanel(w: HWND, sw: HWND, f :HFONT)
{
unsafe
{
match getmode() & 0x10
{
0x10 =>
{
showcaret(w);
*MODE.lock().unwrap() -= 0x10;
user::ShowWindow(sw, user::SW_HIDE);
user::SetFocus(w);
redraw(w, f, 0, 0, 0, 0);
},
_ =>
{
hidecaret(w);
*MODE.lock().unwrap() += 0x10;
user::ShowWindow(sw, user::SW_SHOW);
user::SetFocus(w);
},
}
}
}
pub unsafe extern "system" fn window_proc(w :HWND, msg :UINT, p :WPARAM, l :LPARAM) -> LRESULT
{
match msg
{
user::WM_CREATE =>
{
let param = &*(l as LPCREATESTRUCTW);
#[cfg(target_pointer_width = "32")] {user::SetWindowLongPtrW(w, user::GWLP_USERDATA, param.lpCreateParams as i32);} #[cfg(target_pointer_width = "64")] {user::SetWindowLongPtrW(w, user::GWLP_USERDATA, param.lpCreateParams as isize);} },
user::WM_CHAR =>
{
let mov_ptr = user::GetWindowLongPtrW(w, user::GWLP_USERDATA) as LPVOID;
let mov :&mut MV = &mut *(mov_ptr as *mut MV);
match user::GetAsyncKeyState(user::VK_CONTROL) as u16 & 0x8000
{
0 => edit(w, p, mov), _ => ctrl(w, p, mov),
}
},
user::WM_DROPFILES =>
{
let hdrop = p as shell::HDROP;
let _file = shell::DragQueryFileW(hdrop, 0xFFFFFFFF, ptr::null_mut(), 0);
if _file != 1
{
println!("multiple files not supported");
shell::DragFinish(hdrop);
}
else
{
let mut v = vec![0u16; MAX_PATH as usize];
shell::DragQueryFileW(hdrop, 0, v.as_mut_ptr(), MAX_PATH as u32);
shell::DragFinish(hdrop);
let mut path = String::new();
for val in v.iter()
{
let c = (*val & 0xFF) as u8;
if c == 0 {break;} else { path.push(c as char);}
}
let mov_ptr = user::GetWindowLongPtrW(w, user::GWLP_USERDATA) as LPVOID;
let mov :&mut MV = &mut *(mov_ptr as *mut MV);
let font = mov.font;
file(w, font, path, 0);
}
},
user::WM_LBUTTONDOWN =>
{
setstate(0x80, 0);
let x = winx::GET_X_LPARAM(l);
let y = winx::GET_Y_LPARAM(l);
hidecaret(w);
clickpos(x, y);
showcaret(w);
},
user::WM_LBUTTONUP =>
{
let x = winx::GET_X_LPARAM(l);
let y = winx::GET_Y_LPARAM(l);
hidecaret(w);
clickpos(x, y);
showcaret(w);
setstate(0x08, 1);
},
user::WM_MOUSEMOVE =>
{
user::SetCursor(user::LoadCursorW(ptr::null_mut(), user::IDC_ARROW));
let state = getstate();
match state & 0x80
{
0x80 =>
{
let x = winx::GET_X_LPARAM(l);
let y = winx::GET_Y_LPARAM(l);
let pos = getpos(x,y);
match pos
{
None => {},
_ =>
{
let p = pos.unwrap();
let c = getchar(p.x, p.y);
let mov_ptr = user::GetWindowLongPtrW(w, user::GWLP_USERDATA) as LPVOID;
let mov :&mut MV = &mut *(mov_ptr as *mut MV);
let font = mov.font;
match c
{
None => (),
_ =>
{
let c = c.unwrap();
drawtext(w, font, &CH{x:p.x, y:p.y, c:c}, 1, 1);
let mut buffer = {RBUFFER.lock().unwrap()};
buffer.push(c);
},
}
},
}
},
_=> (),
}
},
user::WM_MOUSEWHEEL =>
{
let delta = user::GET_WHEEL_DELTA_WPARAM(p);
let mov_ptr = user::GetWindowLongPtrW(w, user::GWLP_USERDATA) as LPVOID;
let mov :&mut MV = &mut *(mov_ptr as *mut MV);
let font = mov.font;
match delta {
120 => {wheel_up(w, font);},
-120 => {wheel_down(w, font);},
_ => {},
}
},
user::WM_PAINT =>
{
let state = getstate();
match state & 0x10
{
0x10 =>
{
setstate(0xFFFFFFEF, 1);
let mov_ptr = user::GetWindowLongPtrW(w, user::GWLP_USERDATA) as LPVOID;
let mov :&mut MV = &mut *(mov_ptr as *mut MV);
let font = mov.font;
let vec = {TEXT.lock().unwrap()};
for v in vec.iter() {drawtext(w, font, &CH{x:v.x,y:v.y,c:v.c}, 1, 0);}
},
_ => {},
}
},
user::WM_SIZE =>
{
let w_h = HIWORD(l as u32);
let ch_h = {*CHY.lock().unwrap()} as u16;
if ch_h != 0 {*SCREEN.lock().unwrap() = (w_h / ch_h) as i32 ;}
},
user::WM_SYSCOMMAND =>
{
match p & 0xFFF0
{
user::SC_MINIMIZE => {setstate(0x10, 0);},
user::SC_RESTORE => { },
_ => {},
}
},
user::WM_DESTROY =>
{
shell::DragAcceptFiles(w, 0);
user::PostQuitMessage(0);
},
_ => (),
}
return user::DefWindowProcW( w, msg, p, l);
}
pub unsafe extern "system" fn sub_window_proc(w :HWND, msg :UINT, p :WPARAM, l :LPARAM) -> LRESULT
{
match msg
{
user::WM_CLOSE => {user::DestroyWindow(w);},
user::WM_DESTROY => {user::PostQuitMessage(0);},
_ => (),
}
return user::DefWindowProcW( w, msg, p, l);
}
fn main()
{
unsafe
{
let class_name = to_wstring("window"); let class_name2 = to_wstring("subwindow");
let win_name = to_wstring("read v0.1.1"); let win_name2 = to_wstring("configuration");
let icon_name = to_wstring("./read.ico"); let icon_name2 = to_wstring("./read2.ico");
let icon_name3 = to_wstring("./read4.ico");
let font_name = to_wstring("Dejavu Sans Mono");
let font = gdi::CreateFontW(18, 0, 0, 0,
gdi::FW_LIGHT, 0, 0, 0, gdi::DEFAULT_CHARSET, gdi::OUT_DEFAULT_PRECIS,
gdi::CLIP_DEFAULT_PRECIS, gdi::DEFAULT_QUALITY, gdi::DEFAULT_PITCH,
font_name.as_ptr());
let icon = user::LoadImageW(0 as HINSTANCE, icon_name.as_ptr(), user::IMAGE_ICON, 0, 0,
user::LR_LOADFROMFILE | user::LR_DEFAULTSIZE | user::LR_SHARED);
let icon2 = user::LoadImageW(0 as HINSTANCE, icon_name2.as_ptr(), user::IMAGE_ICON, 0, 0,
user::LR_LOADFROMFILE | user::LR_DEFAULTSIZE | user::LR_SHARED);
let icon3 = user::LoadImageW(0 as HINSTANCE, icon_name3.as_ptr(), user::IMAGE_ICON, 0, 0,
user::LR_LOADFROMFILE | user::LR_DEFAULTSIZE | user::LR_SHARED);
let sidehwnd = window(class_name2, win_name2, Some(sub_window_proc), icon as HICON,
WS_POPUP | WS_BORDER | WS_VISIBLE, W/4, H, 0 as LPVOID);
user::ShowWindow(sidehwnd, user::SW_HIDE);
let mut mov : MV = MV{font :font, save :icon as HICON, edit :icon2 as HICON, visual :icon3 as HICON, sw :sidehwnd};
let mov_ptr : LPVOID = &mut mov as *mut _ as LPVOID;
let hwnd = window(class_name, win_name, Some(window_proc), icon as HICON, WS_OVERLAPPEDWINDOW | WS_VISIBLE, W, H, mov_ptr);
user::ShowWindow(hwnd, user::SW_SHOW);
user::SetParent(sidehwnd, hwnd);
user::SetFocus(hwnd);
let mut msg = user::MSG {hwnd : 0 as HWND,message : 0 as UINT, wParam : 0 as WPARAM, lParam : 0 as LPARAM, time : 0 as DWORD, pt : POINT{x:0, y:0},};
if font != ptr::null_mut() {user::SendMessageW(hwnd, user::WM_SETFONT, font as WPARAM, 1);}
let dc = user::GetDC(hwnd) as HDC;
let mut char_w : INT = 0;
let mut tm = gdi::TEXTMETRICW
{
tmHeight: 0, tmAscent: 0, tmDescent: 0, tmInternalLeading: 0, tmExternalLeading: 0,
tmAveCharWidth: 0, tmMaxCharWidth: 0, tmWeight: 0, tmOverhang: 0, tmDigitizedAspectX: 0,
tmDigitizedAspectY: 0, tmFirstChar: 0, tmLastChar: 0, tmDefaultChar: 0, tmBreakChar: 0,
tmItalic: 0, tmUnderlined: 0, tmStruckOut: 0, tmPitchAndFamily: 0, tmCharSet: 0,
};
gdi::SelectObject(dc, font as HGDIOBJ );
gdi::GetCharWidth32W(dc, 0 as UINT, 0 as UINT, &mut char_w);
gdi::GetTextMetricsW(dc, &mut tm);
user::ReleaseDC(hwnd, dc);
*CHX.lock().unwrap() = char_w;
*CHY.lock().unwrap() = tm.tmHeight;
user::CreateCaret(hwnd, 0 as HBITMAP, 1, tm.tmHeight);
showcaret(hwnd);
shell::DragAcceptFiles(hwnd, 1);
let brush = gdi::CreateSolidBrush(gdi::RGB(R_B,G_B,B_B));
#[cfg(target_pointer_width = "32")]{user::SetClassLongPtrW(hwnd, user::GCLP_HBRBACKGROUND, brush as i32);} #[cfg(target_pointer_width = "64")]{user::SetClassLongPtrW(hwnd, user::GCLP_HBRBACKGROUND, brush as isize);} user::MoveWindow(hwnd, SX, SY, W, H, 1);
loop
{
let m = user::GetMessageW(&mut msg, 0 as HWND, 0, 0);
if msg.message == user::WM_QUIT {break;}
if m > 0 { user::TranslateMessage(&mut msg);user::DispatchMessageW(&mut msg);}
}
}
}