#include "../include/xcv_license.h" //PCH namespace Widgets95 {//-. //<-' extern void xcv_list_scrollbar_callback(ui::bar *sb); static void xcv_textbox_scrollbar_callback(ui::bar *sb) { ui::wordproc *my = dynamic_cast(sb->associated_object); if(!my){ assert(0); return; } //This used to have some code to adjust curr_line by dragging it //along with the scrollbar attached to the first or last visible //line. curr_line was not used or maintained. my->update_and_draw_text(); } /****************************** WIDGETS_95_TextBox::common_construct() **********/ ui::bar *ui::control::scrollbar_init(callback cb) { bar *sb = scrollbar; if(sb&&this!=sb->associated_object) sb->set_object_callback(cb,this); return sb; } /******************************** WIDGETS_95_TextBox::draw_insertion_pt() *********/ namespace xcv_wordproc_gl_caret { //WARNING: I threw this together pretty quickly one //day when I realized this is one way to do a caret. enum{ ms=500 }; static int x,y,h; static int sync = 0; static int xor_bit = 0; static void xor_draw(int i=1) { gl::glEnable(GL_COLOR_LOGIC_OP); gl::glLogicOp(GL_XOR); { gl::glBegin(GL_LINES); window::draw_color(255); while(i-->0) { gl::glVertex2i(x,y); gl::glVertex2i(x,y+h); } gl::glEnd(); } gl::glDisable(GL_COLOR_LOGIC_OP); gl::glLogicOp(GL_COPY); } static void timer(int cmp) { if(!h||cmp!=sync||!e.active_control_ui) { return; } xor_bit = !xor_bit; int old = glutGetWindow(); glutSetWindow(e.active_control_ui->glut_window_id()); { int swap; gl::glGetIntegerv(GL_DRAW_BUFFER,&swap); gl::glDrawBuffer(GL_FRONT); { xor_draw(); } gl::glFlush(); gl::glDrawBuffer(swap); } glutSetWindow(old); glutTimerFunc(ms,timer,cmp); } extern bool callback(ui::control *cc, int ch, int cx, int cy, bool) { //NOTE: I think deactivated controls will send 0,0,0. if(x!=cx||y!=cy) { x = cx; y = cy; h = ch; xor_bit = 0; sync++; if(ch) glutTimerFunc(ms,timer,sync); } if(ch) { x-=cc->_x_abs; y-=cc->_y_abs; xor_draw(xor_bit+1); x+=cc->_x_abs; y+=cc->_y_abs; } else sync++; return false; } } namespace xcv_wordproc_gles_caret { extern bool callback(ui::control *cc, int ch, int cx, int cy, bool) { if(1==glutGet(glutext::GLUT_GLES)) { //TODO: GLES1 has glLogicOp and some form of front buffer //drawing from what I've heard, although gl.h is missing //glDrawBuffer/GL_DRAW_BUFFER. assert(0); } return true; //Just draw a line? } } extern caret_callback *xcv_wordproc_caret_cb() { caret_callback *ccb = e.caret_callback; //2021: GLES 2 can't currently implement XOR or //front buffer drawing. Should revisit this for //GLES 1. if(xcv_gl) return ccb?ccb:&xcv_wordproc_gles_caret::callback; return ccb?ccb:&xcv_wordproc_gl_caret::callback; } void ui::control::pos_caret(int h, int x, int y) { int m[4]; margin_dims(m); if(!_ui) draw: { x+=m[0]; y+=m[1]; window::draw_color(0); gl::glBegin(GL_LINES); gl::glVertex2i(x,y); gl::glVertex2i(x,y+h); gl::glEnd(); return; } else if(this==e::get_caret()) { x+=e.caret_x; y+=e.caret_y; assert(this==_ui->_active_control); } else if(this==e::get_active()) { if(-1!=e.prev_caret_pt) { e.prev_caret_pt = -1; h = 0; } else return; } else return; int cx = 0, cy = 0; if(x>=0&&y>=0&&x_w; int ch = cy+_ui->_h; cx+=x+m[0]+_x_abs; cy+=y+m[1]+_y_abs; if(cx<0||cy<0||cx>=cw||cy>=ch) { h = 0; } } else h = 0; if(xcv_wordproc_caret_cb()(this,h,cx,cy,!_enabled)) { if(h>0) goto draw; } } /****************************** WIDGETS_95_TextBox::draw() **********/ void ui::wordproc::_draw() { _dump("-> DRAW"); box_interface::_draw(); _CLAMP_substr(); /* Begin Drawing Lines of Text */ //_substr_start = _substr_end = 0; int sol,sss = _substr_start; int eol,sse = _substr_end; int len = char_size(); int box_w = box_span(); int lh = line_feed(); //CAUTION: THIS MUST PRECISELY AGREE //WITH _find_insertion_pt. //CAUTION: THIS MUST PRECISELY AGREE //WITH _find_insertion_pt. //CAUTION: THIS MUST PRECISELY AGREE //WITH _find_insertion_pt. const char *text = _text.c_str(); int y = 1; for(sol=eol=sss;eol DRAW"); } /************************************ WIDGETS_95_TextBox::update_area() **********/ void ui::wordproc::_update_area() { //NEW: ALIGN_EXPAND+wrapping is tough. if(!_alignment) { //Don't trust this call. Expanding //wordproc can't support itself. if(_w<=ui_align_expand_span) return; } bar *sb = scrollbar_init(xcv_textbox_scrollbar_callback); int sb2 = sb&&!sb->_hidden?ui_bar_arrow_size:0; if(_tab<=0) //set_tab_span? { if(!_tab) { _tab = 4*chr_span(' '); } else _tab = -_tab; redraw(); assert(_tab); } box_interface::_update_area(); int mw = box_span(); if(mwset_range(); //HACK: ui_wordproc_drop is very small. //This delays update_str_bounds until //update_area. It will be wrong without //tabs anyway. if(_tab) update_substr_bounds(); } //---. }//<-'