1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// external functions

pub use super::*;

/**
 * Allocates heap space for a CWin structure and passes a pointer back.
 */
#[no_mangle]
pub extern fn alloc_win() -> *mut CWin {
  return CWin::new().to_ffi_ptr();
}

#[no_mangle]
pub extern fn alloc_win_detail(title: *const c_char, width: u32, height: u32) -> *mut CWin {
  let title_owned: String = unsafe { // may get null pointer for 'title'
    CStr::from_ptr(title).to_str().unwrap().to_owned()
  };
  return CWin::new_detail(title_owned, width, height).to_ffi_ptr();
}

/**
 * Takes a raw CWin pointer and deallocates it.
 * Deallocation happens when the 'data' variable goes out of scope.
 */
#[no_mangle]
pub extern fn dealloc_win(win_ptr: *mut CWin) {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return;
    }
    let _data = Box::from_raw(win_ptr);
  }
}

#[no_mangle]
pub extern fn add_callback(win_ptr: *mut CWin, ffi_fun: extern fn(*mut CWinRep, *const c_char /* event string */)) {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return;
    }
    (*win_ptr).add_callback_raw(ffi_fun);
  }
}

#[no_mangle]
pub extern fn call_callbacks(win_ptr: *mut CWin, evt_str: *const c_char /* event string */) {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return;
    }
    (*win_ptr).call_raw_callbacks(evt_str);
  }
}

#[no_mangle]
pub extern fn event_loop(win_ptr: *mut CWin, ) {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return;
    }
    (*win_ptr).event_loop();
  }
}

#[no_mangle]
pub extern fn event_tick(win_ptr: *mut CWin, ) -> *const c_char {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return null_mut();
    }
    let evt_str = (*win_ptr).event_tick();
    let safe_cstr : CString = CString::new(evt_str).unwrap();
    let cstr_ptr = safe_cstr.as_ptr();
    std::mem::forget(safe_cstr); // Calling C code is responsible for free-ing memory
    return cstr_ptr;
  }
}

#[no_mangle]
pub extern fn init(win_ptr: *mut CWin, ) {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return;
    }
    (*win_ptr).init();
  }
}

#[no_mangle]
pub extern fn set_rep_exit_flag(win_ptr: *mut CWin, val: libc::c_uchar) {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return;
    }
    println!("set_rep_exit_flag = {}", val != 0);
    (*win_ptr).rep.exit_flag = val != 0;
    // 0 is false, non-zero becomes true.
  }
}

#[no_mangle]
pub extern fn redraw_dirty(win_ptr: *mut CWin) {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return;
    }
    (*win_ptr).redraw_dirty();
  }
}

#[no_mangle]
pub extern fn redraw_box(win_ptr: *mut CWin, x1: u32, y1: u32, x2: u32, y2: u32, ) {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return;
    }
    (*win_ptr).redraw_box(x1 as usize, y1 as usize, x2 as usize, y2 as usize);
  }
}

#[no_mangle]
pub extern fn write_px(win_ptr: *mut CWin, x: u32, y: u32, red: libc::c_uchar, green: libc::c_uchar, blue: libc::c_uchar) {
  unsafe { // unsafe b/c we may get a null pointer for 'win_ptr'
    if win_ptr.is_null() {
      return;
    }
    (*win_ptr).write_px(x, y, [red as u8, green as u8, blue as u8]);
  }
}