Initial commit
This commit is contained in:
parent
015929c965
commit
7e8b9b5570
@ -15,7 +15,7 @@ AM_CPPFLAGS = -D _GNU_SOURCE -I.. -I$(srcdir)/src/libcm -I$(srcdir)/src/libcm/
|
||||
AM_CFLAGS = -Wno-multichar
|
||||
AM_CXXFLAGS =
|
||||
AM_LDFLAGS =
|
||||
MYLIBS = -lpthread -lfftw3f -lfftw3
|
||||
MYLIBS = -lpthread -lfftw3f -lfftw3 -lfltk
|
||||
CMLIBS = src/libcm/libcm.la # autoconfig manual recommends storing direct referenes to non-3rd party libraries rather than using -L and -l
|
||||
|
||||
|
||||
@ -56,6 +56,7 @@ include_HEADERS += $(cmHDR)
|
||||
lib_LTLIBRARIES += src/libcm/libcm.la
|
||||
|
||||
|
||||
src_proj_proj_SOURCES = src/proj/main.c
|
||||
src_proj_proj_LDADD = $(CMLIBS) $(MYLIBS)
|
||||
bin_PROGRAMS += src/proj/proj
|
||||
src_cmflapp_cmflapp_SOURCES = src/cmflapp/main.cpp src/cmflapp/app.h src/cmflapp/app.cpp
|
||||
src_cmflapp_cmflapp_SOURCES += src/cmflapp/Fl_Splitter.h src/cmflapp/Fl_Splitter.cpp
|
||||
src_cmflapp_cmflapp_LDADD = $(CMLIBS) $(MYLIBS)
|
||||
bin_PROGRAMS += src/cmflapp/cmflapp
|
||||
|
@ -3,10 +3,10 @@
|
||||
# this configure.ac or any of the Makefile.am files.
|
||||
#
|
||||
|
||||
AC_INIT([proj],[1.0],[proj@larke.org])
|
||||
AC_INIT([cmflapp],[1.0],[cmflapp@larke.org])
|
||||
AC_CONFIG_AUX_DIR([build-aux]) # put aux files in build-aux
|
||||
AM_INIT_AUTOMAKE([1.9 -Wall foreign subdir-objects]) # subdir-objects needed for non-recursive make
|
||||
AC_CONFIG_SRCDIR([src/proj/main.c])
|
||||
AC_CONFIG_SRCDIR([src/cmflapp/main.cpp])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
|
265
src/cmflapp/Fl_Splitter.cpp
Normal file
265
src/cmflapp/Fl_Splitter.cpp
Normal file
@ -0,0 +1,265 @@
|
||||
// Code based on: http://www.mail-archive.com/fltk@easysw.com/msg04573.html
|
||||
// Lucas Sanner/Ian MacArthur
|
||||
|
||||
#include "Fl_Splitter.h"
|
||||
|
||||
void Fl_HSplitter::draw()
|
||||
{
|
||||
Fl_Group::draw();
|
||||
fl_color(FL_BLACK);
|
||||
fl_line_style( FL_DOT, 1);
|
||||
|
||||
if(bSplit && Fl::event_button1() != 0)
|
||||
{
|
||||
fl_push_clip(x(), y(), w(), h());
|
||||
|
||||
yPos = Fl::event_y();
|
||||
|
||||
if(Fl::event_y() > h() - (border * 2))
|
||||
yPos = h() - (border * 2);
|
||||
|
||||
if(Fl::event_y() < y() + (border * 2))
|
||||
yPos = y() + (border * 2);
|
||||
|
||||
fl_line( x() + border, yPos - 1, x() + w() - (border*2), yPos - 1 );
|
||||
fl_line( x() + border, yPos , x() + w() - (border*2), yPos );
|
||||
fl_line( x() + border, yPos + 1, x() + w() - (border*2), yPos + 1 );
|
||||
|
||||
/*
|
||||
fl_line(
|
||||
x() + border,
|
||||
yPos,
|
||||
x() + w() - (border*2),
|
||||
yPos );
|
||||
|
||||
fl_line(
|
||||
x() + border,
|
||||
yPos + 1,
|
||||
x() + w() - (border*2),
|
||||
yPos + 1 );
|
||||
*/
|
||||
|
||||
fl_pop_clip();
|
||||
}
|
||||
else
|
||||
{
|
||||
fl_push_clip(x(), y(), w(), h());
|
||||
fl_pop_clip();
|
||||
}
|
||||
}
|
||||
|
||||
int Fl_HSplitter::handle(int e)
|
||||
{
|
||||
int ret = Fl_Group::handle(e);
|
||||
|
||||
switch(e)
|
||||
{
|
||||
case FL_MOVE:
|
||||
|
||||
if(Fl::event_y() > hCtnl - border && Fl::event_y() < hCtnl + border)
|
||||
{
|
||||
fl_cursor(FL_CURSOR_NS);
|
||||
bSplit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fl_cursor(FL_CURSOR_DEFAULT);
|
||||
bSplit = false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
case FL_PUSH:
|
||||
|
||||
if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
|
||||
{
|
||||
redraw();
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
case FL_RELEASE:
|
||||
|
||||
if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
|
||||
{
|
||||
container1->resize(x(), y(), w(), yPos - y());
|
||||
hCtnl = yPos;
|
||||
container2->resize(x(),hCtnl, w(), h() - (yPos - y()));
|
||||
|
||||
if( stretchTopFl )
|
||||
init_sizes();
|
||||
|
||||
bSplit = false;
|
||||
redraw();
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
case FL_DRAG:
|
||||
|
||||
if(bSplit && Fl::event_state(FL_BUTTON1) != 0)
|
||||
redraw();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
Fl_HSplitter::Fl_HSplitter(int x, int y, int w, int h, int h1, const char *l, bool stretchBotFl)
|
||||
: Fl_Group(x, y, w, h, l)
|
||||
{
|
||||
int h2 = h - h1;
|
||||
|
||||
begin();
|
||||
container1 = new Splitter_Container(x, y, w, h1);
|
||||
//container1->color((Fl_Color) FL_RED);
|
||||
end();
|
||||
|
||||
begin();
|
||||
container2 = new Splitter_Container(x, y + h1, w, h2);
|
||||
//container2->color((Fl_Color) FL_BLUE);
|
||||
end();
|
||||
|
||||
hCtnl = y + h1;
|
||||
bSplit = false;
|
||||
stretchTopFl = !stretchBotFl;
|
||||
|
||||
border = Fl::box_dy(FL_DOWN_BOX);
|
||||
|
||||
if( stretchTopFl )
|
||||
resizable(container1);
|
||||
}
|
||||
|
||||
void Fl_HSplitter::resize_splitter(int x, int y, int w, int h)
|
||||
{
|
||||
resize(x, y, w, h);
|
||||
|
||||
if( stretchTopFl )
|
||||
{
|
||||
hCtnl = container1->h() + y;
|
||||
yPos = hCtnl;
|
||||
}
|
||||
else
|
||||
{
|
||||
container1->resize(x, y, w, hCtnl - y);
|
||||
container2->resize(x, hCtnl, w, h - (hCtnl - y));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Fl_VSplitter::draw()
|
||||
{
|
||||
Fl_Group::draw();
|
||||
fl_color(FL_BLACK);
|
||||
fl_line_style( FL_DOT, 1);
|
||||
|
||||
if(bSplit && Fl::event_button1() != 0)
|
||||
{
|
||||
fl_push_clip(x(), y(), w(), h());
|
||||
|
||||
xPos = Fl::event_x();
|
||||
|
||||
if(Fl::event_x() > w() - (border * 2))
|
||||
xPos = w() - (border * 2);
|
||||
|
||||
if(Fl::event_x() < x() + (border * 2))
|
||||
xPos = x() + (border * 2);
|
||||
|
||||
fl_line(xPos - 1, y() + border, xPos - 1, y() + h() - (border * 2));
|
||||
fl_line(xPos, y() + border, xPos, y() + h() - (border * 2));
|
||||
fl_line(xPos + 1, y() + border, xPos + 1, y() + h() - (border * 2));
|
||||
|
||||
fl_pop_clip();
|
||||
}
|
||||
else
|
||||
{
|
||||
fl_push_clip(x(), y(), w(), h());
|
||||
fl_pop_clip();
|
||||
}
|
||||
}
|
||||
|
||||
int Fl_VSplitter::handle(int e)
|
||||
{
|
||||
int ret = Fl_Group::handle(e);
|
||||
|
||||
switch(e)
|
||||
{
|
||||
case FL_MOVE:
|
||||
|
||||
if(Fl::event_x() > wCtn1 - border && Fl::event_x() < wCtn1 + border)
|
||||
{
|
||||
fl_cursor(FL_CURSOR_WE);
|
||||
bSplit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fl_cursor(FL_CURSOR_DEFAULT);
|
||||
bSplit = false;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
case FL_PUSH:
|
||||
|
||||
if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
|
||||
{
|
||||
redraw();
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
case FL_RELEASE:
|
||||
|
||||
if(Fl::event_button() == FL_LEFT_MOUSE && bSplit)
|
||||
{
|
||||
container1->resize(x(), y(), xPos, h());
|
||||
wCtn1 = xPos;
|
||||
container2->resize(wCtn1, y(), w() - wCtn1, h());
|
||||
bSplit = false;
|
||||
redraw();
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
case FL_DRAG:
|
||||
|
||||
if(bSplit && Fl::event_state(FL_BUTTON1) != 0)
|
||||
redraw();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
Fl_VSplitter::Fl_VSplitter(int x, int y, int w, int h, const char *l)
|
||||
: Fl_Group(x, y, w, h, l)
|
||||
{
|
||||
begin();
|
||||
container1 = new Splitter_Container(x, y, w / 2, h);
|
||||
//container1->color((Fl_Color) FL_RED);
|
||||
end();
|
||||
|
||||
begin();
|
||||
container2 = new Splitter_Container(x + (w / 2), y, w / 2, h);
|
||||
//container2->color((Fl_Color) FL_BLUE);
|
||||
end();
|
||||
|
||||
wCtn1 = w / 2;
|
||||
bSplit = false;
|
||||
|
||||
border = Fl::box_dx(FL_DOWN_BOX);
|
||||
|
||||
}
|
||||
|
||||
void Fl_VSplitter::resize_splitter(int x, int y, int w, int h)
|
||||
{
|
||||
resize(x, y, w, h);
|
||||
container1->resize(x, y, wCtn1, h);
|
||||
container2->resize(wCtn1, y, w - wCtn1, h);
|
||||
}
|
||||
|
74
src/cmflapp/Fl_Splitter.h
Normal file
74
src/cmflapp/Fl_Splitter.h
Normal file
@ -0,0 +1,74 @@
|
||||
// Code based on: http://www.mail-archive.com/fltk@easysw.com/msg04573.html
|
||||
// Lucas Sanner/Ian MacArthur
|
||||
|
||||
#ifndef Fl_Splitter_h
|
||||
#define Fl_Splitter_h
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Group.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
|
||||
class Splitter_Container : public Fl_Group
|
||||
{
|
||||
void draw()
|
||||
{
|
||||
fl_push_clip(x(), y(), w(), h());
|
||||
Fl_Group::draw();
|
||||
fl_pop_clip();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Splitter_Container(int x, int y, int w, int h, char *l = NULL)
|
||||
: Fl_Group(x, y, w, h, l)
|
||||
{
|
||||
//box(FL_DOWN_BOX);
|
||||
}
|
||||
};
|
||||
|
||||
class Fl_HSplitter : public Fl_Group
|
||||
{
|
||||
int hCtnl, border, yPos;
|
||||
bool bSplit;
|
||||
bool stretchTopFl; // set to make top container stretch when splitter is resized
|
||||
int hh2;
|
||||
|
||||
void draw();
|
||||
|
||||
int handle(int e);
|
||||
|
||||
public:
|
||||
|
||||
Splitter_Container *container1, *container2;
|
||||
|
||||
Fl_HSplitter(int x, int y, int w, int h, int h1, const char *l=NULL, bool stretchBotFl=false);
|
||||
|
||||
void resize_splitter(int x, int y, int w, int h);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class Fl_VSplitter : public Fl_Group
|
||||
{
|
||||
|
||||
int wCtn1, border, xPos;
|
||||
bool bSplit;
|
||||
|
||||
void draw();
|
||||
int handle(int e);
|
||||
|
||||
public:
|
||||
|
||||
Splitter_Container *container1, *container2;
|
||||
|
||||
Fl_VSplitter(int x, int y, int w, int h, const char *l = NULL);
|
||||
|
||||
void resize_splitter(int x, int y, int w, int h);
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
555
src/cmflapp/app.cpp
Normal file
555
src/cmflapp/app.cpp
Normal file
@ -0,0 +1,555 @@
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Widget.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Text_Buffer.H>
|
||||
#include <FL/Fl_Text_Display.H>
|
||||
#include <FL/Fl_Tabs.H>
|
||||
#include <FL/Fl_Menu_Item.H>
|
||||
#include <FL/Fl_Menu_Bar.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Check_Button.H>
|
||||
#include <FL/Fl_Menu_Button.H>
|
||||
#include <FL/Fl_Value_Input.H>
|
||||
#include <FL/Fl_Value_Slider.H>
|
||||
#include <FL/Fl_Input.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_File_Chooser.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#include "Fl_Splitter.h"
|
||||
|
||||
#include "cmPrefix.h"
|
||||
#include "cmGlobal.h"
|
||||
#include "cmRpt.h"
|
||||
#include "cmErr.h"
|
||||
#include "cmCtx.h"
|
||||
#include "cmMem.h"
|
||||
#include "cmMallocDebug.h"
|
||||
#include "cmFileSys.h"
|
||||
#include "cmThread.h"
|
||||
|
||||
#include "appErr.h"
|
||||
#include "app.h"
|
||||
|
||||
class drawWnd : public Fl_Widget
|
||||
{
|
||||
public:
|
||||
drawWnd(app* ap, int x, int y, int w, int h, const char* label = NULL );
|
||||
virtual ~drawWnd();
|
||||
|
||||
virtual int handle(int event);
|
||||
virtual void resize(int x, int y, int w, int h );
|
||||
|
||||
protected:
|
||||
virtual void draw();
|
||||
|
||||
private:
|
||||
app* _app;
|
||||
};
|
||||
|
||||
drawWnd::drawWnd(app* ap, int x, int y, int w, int h, const char* label )
|
||||
: Fl_Widget(x,y,w,h,label),
|
||||
_app(ap)
|
||||
{}
|
||||
|
||||
drawWnd::~drawWnd()
|
||||
{}
|
||||
|
||||
int drawWnd::handle(int event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case FL_PUSH:
|
||||
{
|
||||
const char* label;
|
||||
switch( Fl::event_button() )
|
||||
{
|
||||
case FL_LEFT_MOUSE: label = "left"; break;
|
||||
case FL_RIGHT_MOUSE: label = "right"; break;
|
||||
case FL_MIDDLE_MOUSE: label = "middle"; break;
|
||||
default:
|
||||
label = "none";
|
||||
}
|
||||
|
||||
_app->print("%i %i %s\n",Fl::event_x(),Fl::event_y(),label);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return Fl_Widget::handle(event);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void drawWnd::resize(int x, int y, int w, int h )
|
||||
{
|
||||
// must call base to make size change
|
||||
Fl_Widget::resize(x,y,w,h);
|
||||
}
|
||||
|
||||
void drawWnd::draw()
|
||||
{
|
||||
int offs = 10;
|
||||
//fl_draw_box(FL_DOWN_BOX,x()+10,y()+10,w()-20,h()-20,FL_RED);
|
||||
//fl_frame("XXXX",x()+offs,y()+offs,w()-2*offs,h()-2*offs);
|
||||
fl_line_style(FL_SOLID,1,NULL);
|
||||
fl_color(FL_RED);
|
||||
fl_line(x()+offs,y()+offs,x()+w()-offs,y()+h()-offs);
|
||||
|
||||
|
||||
int x = w()/2;
|
||||
int y = h()/2;
|
||||
|
||||
fl_color(FL_BLACK);
|
||||
fl_draw(90,"string",x,y);
|
||||
|
||||
// XXXXXXX
|
||||
// X00000X
|
||||
// X00000X
|
||||
// X00X00X
|
||||
// X00000X
|
||||
// X00000X
|
||||
// XXXXXXX
|
||||
|
||||
fl_rect(x-3,y-3,7,7);
|
||||
fl_point(x,y);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
app::app(cmCtx_t* ctx, cmTsMp1cH_t printqH, int w, int h, const char* label, int argc, char* argv[])
|
||||
: Fl_Double_Window(w,h,label), _timerPeriodSecs(0),
|
||||
_ctx(ctx), _splt(NULL),_buf(NULL),_con(NULL),_tabs(NULL),_menu(NULL),
|
||||
_printqH(printqH),_printFl(0)
|
||||
{
|
||||
|
||||
// install a callback to cleanup when the app window closes
|
||||
// (the btn and menu callbacks also rely on a pointer to 'this' being found in app.user_data()
|
||||
// see _getApp())
|
||||
callback(_s_callback,this);
|
||||
|
||||
// the main window is divided between the menu bar on top
|
||||
// and a horizontal splitter on the bottom
|
||||
begin();
|
||||
createMenu(w,kMenuH);
|
||||
_splt = new Fl_HSplitter(0, kMenuH, w, h-kStatusH, h-kStatusH-100);
|
||||
end();
|
||||
|
||||
// Create a text display object for console output and
|
||||
// add it to the lower splitter area
|
||||
_buf = new Fl_Text_Buffer();
|
||||
_con = new Fl_Text_Display(_splt->container2->x(),_splt->container2->y(),_splt->container2->w(),_splt->container2->h());
|
||||
_con->buffer(_buf);
|
||||
_splt->container2->add(_con);
|
||||
|
||||
// create tabbed windows
|
||||
const char* titles[] = { "Title 1", "Title 2" };
|
||||
_create_tabs(2,titles);
|
||||
|
||||
// make the splitter the resizable group element (thereby making the menu non-resizable).
|
||||
// see:http://fltk.org/articles.php?L415+I0+T+M1000+P1
|
||||
resizable(_splt);
|
||||
show(argc, argv);
|
||||
|
||||
// The application is now visible.
|
||||
// direct all output to the console window
|
||||
cmRptSetup(&_ctx->rpt,_s_print,_s_print, this);
|
||||
cmTsMp1cSetCbFunc(_printqH, _s_print_queue_cb, this );
|
||||
|
||||
|
||||
// install a timer
|
||||
_timerPeriodSecs = 0.1;
|
||||
Fl::add_timeout(_timerPeriodSecs,app::_s_timer_cb,this);
|
||||
|
||||
// install an idle callback
|
||||
//Fl::add_idle(_s_idle_cb,this);
|
||||
|
||||
print("Started!\n");
|
||||
}
|
||||
|
||||
app::~app()
|
||||
{}
|
||||
|
||||
void app::createControls(Fl_Group* grp)
|
||||
{
|
||||
const int vBord = 3;
|
||||
const int ctl_width = 100;
|
||||
int xx = grp->x() + 5;
|
||||
int yy = grp->y() + vBord;
|
||||
|
||||
Fl_Check_Button* cbt = new Fl_Check_Button(xx,yy,ctl_width,kCtlH,"Check");
|
||||
cbt->callback( _s_btn_cb, kBtn1MId );
|
||||
yy += cbt->h() + vBord;
|
||||
|
||||
Fl_Button* btn = new Fl_Button(xx,yy,ctl_width,kCtlH,"Button");
|
||||
btn->callback( _s_btn_cb, kBtn2MId );
|
||||
yy += btn->h() + vBord;
|
||||
|
||||
// menu buttons callback through menuCallback() not btnCallback()
|
||||
Fl_Menu_Button* mbt = new Fl_Menu_Button(xx,yy,ctl_width,kCtlH,"Menu");
|
||||
|
||||
mbt->add("Item 1",0,_s_menu_btn_cb, (void*)kMenuBtn1MId, 0);
|
||||
mbt->add("Item 2",0,_s_menu_btn_cb, (void*)kMenuBtn2MId, 0);
|
||||
yy += mbt->h() + vBord;
|
||||
|
||||
Fl_Value_Input* vip = new Fl_Value_Input(xx,yy,ctl_width/2,kCtlH,"Value In");
|
||||
vip->callback(_s_value_cb, kValue1MId );
|
||||
vip->align(FL_ALIGN_RIGHT); // place label to the right of the input ctl
|
||||
// Only make the callback when the enter key is struck or the ctl loses focus and the value has changed.
|
||||
// Removing this line causes the callback whenever the input changes.
|
||||
vip->when(FL_WHEN_ENTER_KEY | FL_WHEN_RELEASE );
|
||||
vip->bounds(-10.0,10.0);
|
||||
vip->step(0.1);
|
||||
yy += vip->h() + vBord;
|
||||
|
||||
Fl_Value_Slider* sdp = new Fl_Value_Slider(xx,yy,ctl_width,kCtlH,"Slider");
|
||||
sdp->callback(_s_value_cb, kValue2MId );
|
||||
sdp->align(FL_ALIGN_RIGHT);
|
||||
sdp->type(FL_HOR_NICE_SLIDER);
|
||||
sdp->bounds(-10.0,10.0);
|
||||
sdp->step(0.1);
|
||||
yy += sdp->h() + vBord;
|
||||
|
||||
Fl_Input* inp = new Fl_Input(xx,yy,ctl_width/2,kCtlH,"Text");
|
||||
inp->callback(_s_input_cb,kInput1MId);
|
||||
inp->align(FL_ALIGN_RIGHT);
|
||||
yy += inp->h() + vBord;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void app::initializeTab(int tabIndex, int x, int y, int w, int h, const char* label)
|
||||
{
|
||||
switch(tabIndex)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
Fl_Group* grp = new Fl_Group(x,y,w,h,label);
|
||||
grp->begin();
|
||||
createControls(grp);
|
||||
grp->end();
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
Fl_Group* grp = new Fl_Group(x,y,w,h,label);
|
||||
grp->begin();
|
||||
_draw = new drawWnd(this,x,y,w,h,NULL);
|
||||
grp->end();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void app::createMenu(int w, int h)
|
||||
{
|
||||
Fl_Menu_Item items[] =
|
||||
{
|
||||
{ "&File", 0, 0, 0, FL_SUBMENU },
|
||||
{ "&New File", FL_COMMAND + 'n', (Fl_Callback*)_s_menu_cb, (void*)kFileNewMId },
|
||||
{ "&Open File", FL_COMMAND + 'o', (Fl_Callback*)_s_menu_cb, (void*)kFileOpenMId },
|
||||
{ 0 },
|
||||
{ "&Edit", 0, 0, 0, FL_SUBMENU },
|
||||
{ "&Copy", FL_COMMAND + 'c', (Fl_Callback*)_s_menu_cb, (void*)kEditCopyMId },
|
||||
{ "&Paste", FL_COMMAND + 'v', (Fl_Callback*)_s_menu_cb, (void*)kEditPasteMId },
|
||||
{ 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
_menu = new Fl_Menu_Bar(0,0,w,h);
|
||||
_menu->copy(items);
|
||||
}
|
||||
|
||||
void app::menuCallback(const Fl_Menu_Item* mip, long int id)
|
||||
{
|
||||
switch(id)
|
||||
{
|
||||
case kFileOpenMId:
|
||||
{
|
||||
// file chooser demo
|
||||
|
||||
const char* pathStr = cmFsUserDir(); // make the default dir the user's home dir
|
||||
const char patStr[] = "Text Files (*.txt)\tAudio Files (*.{wav,aif,aiff})"; // All Files (*.*) is append to this automatically
|
||||
const char titleStr[] = "Select files";
|
||||
|
||||
Fl_File_Chooser fc = Fl_File_Chooser(pathStr,patStr,Fl_File_Chooser::MULTI,titleStr);
|
||||
|
||||
fc.preview(0); // default the previous option to 'off'.
|
||||
fc.show(); // show the chooser
|
||||
|
||||
// make the chooser modal
|
||||
while( fc.shown() )
|
||||
Fl::wait();
|
||||
|
||||
// print the selected files
|
||||
int i;
|
||||
for(i=1; i<=fc.count(); ++i)
|
||||
print("%i %s\n",i,cmStringNullGuard(fc.value(i)));
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
print("%i %s\n",id,mip->label());
|
||||
}
|
||||
|
||||
void app::btnCallback(const Fl_Button* bp, int id )
|
||||
{
|
||||
print("%i %s %i\n",id,bp->label(),bp->value());
|
||||
}
|
||||
|
||||
void app::valueCallback(const Fl_Valuator* vp, int id )
|
||||
{
|
||||
print("%i %s %f\n",id,vp->label(),vp->value());
|
||||
}
|
||||
|
||||
void app::inputCallback(const Fl_Input* ip, int id )
|
||||
{
|
||||
print("%i %s %s\n",id,ip->label(),ip->value());
|
||||
}
|
||||
|
||||
void app::appCallback(Fl_Widget* wp)
|
||||
{
|
||||
switch( Fl::event() )
|
||||
{
|
||||
case FL_CLOSE:
|
||||
{
|
||||
|
||||
/*
|
||||
int cc = _closeCnt;
|
||||
|
||||
// attempt to shut down the pgm
|
||||
_closeCnt += finalizePgm() == false;
|
||||
|
||||
// the first time the pgm fails to shut down
|
||||
// do not allow the pgm to close the main window
|
||||
// this will give a chance for the error messages
|
||||
// to be diplayed in the console - all successive
|
||||
// times the return value from finalizePgm() is
|
||||
|
||||
// ignored and the program is terminated.
|
||||
if( _closeCnt == 1 && cc==0)
|
||||
{
|
||||
// send a strong hint that a problem occurred on shutdown
|
||||
// and prevent the app from receiving events that might cause it to
|
||||
// crash
|
||||
deactivate();
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
// When all windows are windows are closed then the app.
|
||||
// will close - so hiding the application window
|
||||
// causes the program to close.
|
||||
//
|
||||
// Note that simply returning from this callback will
|
||||
// prevent the application from closing. Because the existence
|
||||
// of the callback alone is enough to disable default
|
||||
// event handling.
|
||||
hide();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
bool app::idleCallback()
|
||||
{ return true; }
|
||||
|
||||
|
||||
bool app::timerCallback()
|
||||
{
|
||||
_checkPrintQueue();
|
||||
return true;
|
||||
}
|
||||
|
||||
void app::error( const char* fmt, ... )
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl,fmt);
|
||||
|
||||
int bufCharCnt = 511;
|
||||
char buf[bufCharCnt+1];
|
||||
|
||||
int n = vsnprintf(buf,bufCharCnt,fmt,vl);
|
||||
|
||||
if( n > 0 )
|
||||
print("%s Error: %s\n",label(),buf);
|
||||
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
void app::vprint(const char* fmt, va_list vl )
|
||||
{
|
||||
int bufCharCnt = 511;
|
||||
char buf[bufCharCnt+1];
|
||||
|
||||
int n = vsnprintf(buf,bufCharCnt,fmt,vl);
|
||||
|
||||
if( n > 0 )
|
||||
{
|
||||
// if the print queue exists (it might not during startup or shutdown) ...
|
||||
if( cmTsMp1cIsValid(_printqH) )
|
||||
{
|
||||
cmThRC_t thRC;
|
||||
|
||||
// ... enqueue the text to print
|
||||
if((thRC = cmTsMp1cEnqueueMsg(_printqH,buf,n+1)) != kOkThRC && _printFl==0 )
|
||||
{
|
||||
// Print queue error msg's directly to stdout rather than throught
|
||||
// the error mechanism - this prevents generating a stack overflow
|
||||
// when the print queue runs out of space and attempts to print a
|
||||
// 'queue out of memory' error msg.
|
||||
// The queue itself does will not print errors because it does
|
||||
// not have a valid cmRpt_t pointer. See cmMp1cCreate() above.
|
||||
++_printFl;
|
||||
cmErrMsg(&_ctx->err,kQueueFailAppRC,"Print enqueue failed.");
|
||||
--_printFl;
|
||||
}
|
||||
}
|
||||
else
|
||||
_print(buf); // ... otherwise just send the text directly to the output console
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void app::print( const char* fmt, ... )
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl,fmt);
|
||||
vprint(fmt,vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
void app::_s_menu_cb(Fl_Widget* wp, void* data)
|
||||
{
|
||||
const Fl_Menu_Item* mip;
|
||||
app* ap;
|
||||
|
||||
if((ap=_getApp(wp)) != NULL )
|
||||
if((mip = ap->_menu->mvalue()) != NULL )
|
||||
ap->menuCallback(mip,(long int)mip->user_data());
|
||||
}
|
||||
|
||||
void app::_s_menu_btn_cb(Fl_Widget* wp, void* data)
|
||||
{
|
||||
const Fl_Menu_Button* bp;
|
||||
const Fl_Menu_Item* mip;
|
||||
app* ap;
|
||||
|
||||
if((ap=_getApp(wp)) != NULL )
|
||||
if((bp = static_cast<Fl_Menu_Button*>(wp)) != NULL )
|
||||
if((mip = bp->mvalue()) != NULL)
|
||||
ap->menuCallback(mip,(long int)data);
|
||||
}
|
||||
|
||||
void app::_s_btn_cb(Fl_Widget* wp, long data )
|
||||
{
|
||||
app* ap;
|
||||
|
||||
if((ap = _getApp(wp)) != NULL )
|
||||
if( wp != NULL )
|
||||
ap->btnCallback( static_cast<const Fl_Button*>(wp),data);
|
||||
}
|
||||
|
||||
void app::_s_value_cb( Fl_Widget* wp, long data)
|
||||
{
|
||||
app* ap;
|
||||
Fl_Valuator* vp;
|
||||
|
||||
if((ap = _getApp(wp)) != NULL )
|
||||
if((vp = static_cast<Fl_Valuator*>(wp)) != NULL)
|
||||
ap->valueCallback(vp,data);
|
||||
}
|
||||
|
||||
void app::_s_input_cb( Fl_Widget* wp, long data)
|
||||
{
|
||||
app* ap;
|
||||
Fl_Input* inp;
|
||||
|
||||
if((ap = _getApp(wp)) != NULL)
|
||||
if((inp = static_cast<Fl_Input*>(wp)) != NULL )
|
||||
ap->inputCallback(inp,data);
|
||||
}
|
||||
|
||||
void app::_s_callback(Fl_Widget* wp, void* data)
|
||||
{ ((app*)data)->appCallback(wp); }
|
||||
|
||||
void app::_s_idle_cb(void *data)
|
||||
{
|
||||
app* thisPtr = (app*)data;
|
||||
|
||||
if( thisPtr->idleCallback() == false )
|
||||
Fl::remove_idle(_s_idle_cb,data);
|
||||
}
|
||||
|
||||
void app::_s_timer_cb(void* userPtr)
|
||||
{
|
||||
app* thisPtr = (app*)userPtr;
|
||||
|
||||
if( thisPtr->timerCallback() )
|
||||
Fl::repeat_timeout(thisPtr->_timerPeriodSecs,_s_timer_cb,userPtr);
|
||||
}
|
||||
|
||||
void app::_s_print( void* userPtr, const char* text )
|
||||
{ ((app*)userPtr)->print(text); }
|
||||
|
||||
|
||||
void app::_create_tabs(int titleCnt, const char* titleArray[])
|
||||
{
|
||||
// Create a tab view and added it to the upper splitter area
|
||||
_tabs = new Fl_Tabs(_splt->container1->x(),_splt->container1->y(),_splt->container1->w(),_splt->container1->h());
|
||||
_splt->container1->add(_tabs);
|
||||
|
||||
int tx,ty,th,tw,i;
|
||||
_tabs->client_area(tx,ty,tw,th);
|
||||
|
||||
for(i=0; i<titleCnt; ++i)
|
||||
{
|
||||
_tabs->begin();
|
||||
initializeTab(i,tx,ty,tw,th,titleArray[i]);
|
||||
_tabs->end();
|
||||
}
|
||||
|
||||
// Create an empty tab group and make it resizable
|
||||
// to prevent the other tab groups from being resizable.
|
||||
_tabs->begin();
|
||||
_tabs->resizable(new Fl_Group(tx,ty+30,1,1));
|
||||
_tabs->end();
|
||||
}
|
||||
|
||||
app* app::_getApp( Fl_Widget* w )
|
||||
{
|
||||
// walk up the widget tree until the top widget is found
|
||||
Fl_Group* gp = w->parent();
|
||||
while( gp->parent() != NULL )
|
||||
gp=gp->parent();
|
||||
|
||||
// the user data for the top widget is a pointer app - as set in: callback(_s_callback,this);
|
||||
return (app*)gp->user_data();
|
||||
}
|
||||
|
||||
cmRC_t app::_s_print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
|
||||
{
|
||||
app* ap = (app*)userCbPtr;
|
||||
ap->_print((const char*)msgDataPtr);
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
void app::_checkPrintQueue()
|
||||
{
|
||||
while( cmTsMp1cMsgWaiting(_printqH) )
|
||||
if( cmTsMp1cDequeueMsg(_printqH, NULL, 0) != kOkThRC )
|
||||
error("Print dequeue failed.");
|
||||
}
|
||||
|
||||
void app::_print( const char* text )
|
||||
{
|
||||
if( _con != NULL )
|
||||
_con->insert(text);
|
||||
}
|
119
src/cmflapp/app.h
Normal file
119
src/cmflapp/app.h
Normal file
@ -0,0 +1,119 @@
|
||||
#ifndef app_h
|
||||
#define app_h
|
||||
|
||||
class Fl_HSplitter;
|
||||
class Fl_Text_Buffer;
|
||||
class Fl_Text_Display;
|
||||
class Fl_Box;
|
||||
class Fl_Tabs;
|
||||
struct Fl_Menu_Item;
|
||||
class Fl_Menu_Bar;
|
||||
class Fl_Group;
|
||||
class Fl_Button;
|
||||
class Fl_Valuator;
|
||||
class Fl_Input;
|
||||
class drawWnd;
|
||||
|
||||
class app : public Fl_Double_Window
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
// widget id's for widgets created by createControls()
|
||||
enum
|
||||
{
|
||||
kFileOpenMId,
|
||||
kFileNewMId,
|
||||
kEditCopyMId,
|
||||
kEditPasteMId,
|
||||
|
||||
kBtn1MId,
|
||||
kBtn2MId,
|
||||
kBtn3MId,
|
||||
|
||||
kMenuBtn1MId,
|
||||
kMenuBtn2MId,
|
||||
|
||||
kValue1MId,
|
||||
kValue2MId,
|
||||
|
||||
kInput1MId
|
||||
};
|
||||
|
||||
app(cmCtx_t* ctx, cmTsMp1cH_t printqH, int w, int h, const char *l, int argc, char *argv[]);
|
||||
virtual ~app();
|
||||
|
||||
// Example tabbed window initialization example function
|
||||
// which also demonstrates some widgets
|
||||
void createControls(Fl_Group* grp);
|
||||
|
||||
// called once from app() to initialize each tabbed window
|
||||
virtual void initializeTab(int tabIndex, int x, int y, int w, int h, const char* label);
|
||||
|
||||
// Create the application menu
|
||||
virtual void createMenu( int menuWidth, int menuHeight );
|
||||
|
||||
// Widget type specific callbacks
|
||||
virtual void menuCallback( const Fl_Menu_Item* ip, long int id ); // menu and menu btn callback
|
||||
virtual void btnCallback( const Fl_Button* bp, int id ); // btn callback
|
||||
virtual void valueCallback(const Fl_Valuator* vp, int id ); // valuator callback
|
||||
virtual void inputCallback(const Fl_Input* ip, int id ); // text input callback
|
||||
|
||||
virtual void appCallback(Fl_Widget* wp); // app event callback
|
||||
virtual bool idleCallback(); // return false to stop callback
|
||||
virtual bool timerCallback(); // return false to stop callback
|
||||
|
||||
void error( const char* fmt, ... ); // report on error
|
||||
|
||||
// print to the console
|
||||
virtual void vprint( const char* fmt, va_list vl );
|
||||
virtual void print( const char* fmt, ... );
|
||||
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
kStatusH = 30,
|
||||
kMenuH = 30,
|
||||
kCtlH = 30
|
||||
};
|
||||
|
||||
// static callbacks
|
||||
static void _s_menu_cb( Fl_Widget* wp, void* data); // menu item callback
|
||||
static void _s_menu_btn_cb(Fl_Widget* wp, void* data); // menu btn callback
|
||||
static void _s_btn_cb( Fl_Widget* wp, long data); // button callback
|
||||
static void _s_value_cb( Fl_Widget* wp, long data); // value input or slider callback
|
||||
static void _s_input_cb( Fl_Widget* wp, long data); // text input callback
|
||||
static void _s_callback( Fl_Widget* wp, void* data); // main app callback
|
||||
|
||||
static void _s_idle_cb( void* data); // idle callback
|
||||
static void _s_timer_cb( void* userPtr); // timer callback
|
||||
static void _s_print( void* userPtr, const char* text ); // print text to the console
|
||||
|
||||
void _create_tabs(int titleCnt, const char* titleArray[]);
|
||||
|
||||
// walk down the widget tree until the app (root) widget is located
|
||||
static app* _getApp( Fl_Widget* w );
|
||||
|
||||
// called internally by cmTsQueueDequeue() to send text to _print()
|
||||
static cmRC_t _s_print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr );
|
||||
|
||||
// called periodically to check the print queue for waiting text.
|
||||
void _checkPrintQueue();
|
||||
|
||||
// send a string of text directly to the output console window
|
||||
void _print( const char* text );
|
||||
|
||||
double _timerPeriodSecs; // repeat period for the timer callback
|
||||
|
||||
cmCtx_t* _ctx; //
|
||||
Fl_HSplitter* _splt; // main splitter window
|
||||
Fl_Text_Buffer* _buf; // text buffer used by _con
|
||||
Fl_Text_Display* _con; // text console output window
|
||||
Fl_Tabs* _tabs; // tabs window
|
||||
Fl_Menu_Bar* _menu; // app. menu
|
||||
drawWnd* _draw; // custom widget
|
||||
cmTsMp1cH_t _printqH; // thread-safe queue for controlling access to the output console from multiple threads
|
||||
int _printFl; // used to prevent recursion due to throwing printing error
|
||||
};
|
||||
|
||||
#endif
|
24
src/cmflapp/appErr.h
Normal file
24
src/cmflapp/appErr.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef appErr_h
|
||||
#define appErr_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
kOkAppRC,
|
||||
kQueueFailAppRC,
|
||||
kFileSysFailAppRC,
|
||||
kMemFailAppRC,
|
||||
kTextSysFailAppRC,
|
||||
kPrefsFailAppRC
|
||||
};
|
||||
|
||||
typedef unsigned cmAppRC_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
110
src/cmflapp/main.cpp
Normal file
110
src/cmflapp/main.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include <FL/Fl.H>
|
||||
#include <Fl/fl_draw.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
|
||||
#include "cmPrefix.h"
|
||||
#include "cmGlobal.h"
|
||||
#include "cmFloatTypes.h"
|
||||
#include "cmRpt.h"
|
||||
#include "cmErr.h"
|
||||
#include "cmCtx.h"
|
||||
#include "cmMem.h"
|
||||
#include "cmMallocDebug.h"
|
||||
#include "cmLinkedHeap.h"
|
||||
#include "cmThread.h"
|
||||
#include "cmFileSys.h"
|
||||
#include "cmText.h"
|
||||
|
||||
#include "appErr.h"
|
||||
#include "app.h"
|
||||
|
||||
|
||||
|
||||
|
||||
void print( void*, const cmChar_t* text)
|
||||
{ puts(text); }
|
||||
|
||||
cmRC_t print_queue_cb(void* userCbPtr, unsigned msgByteCnt, const void* msgDataPtr )
|
||||
{
|
||||
print(NULL,(const char*)msgDataPtr);
|
||||
return cmOkRC;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
cmCtx_t ctx;
|
||||
cmTsMp1cH_t printqH = cmTsMp1cNullHandle;
|
||||
int appWndW = 1000;
|
||||
int appWndH = 750;
|
||||
const char* appPrefDir = "gv";
|
||||
const char* appTitle = "GV Console";
|
||||
bool memDebugFl = cmDEBUG_FL;
|
||||
unsigned memPadByteCnt = memDebugFl ? 8 : 0;
|
||||
unsigned memAlignByteCnt = 16;
|
||||
unsigned memFlags = memDebugFl ? (kTrackMmFl | kDeferFreeMmFl | kFillUninitMmFl) : 0;
|
||||
|
||||
cmCtxSetup(&ctx,appTitle,print,print,NULL,memPadByteCnt,memAlignByteCnt,memFlags);
|
||||
|
||||
// initialize the memory mgr
|
||||
if(cmMdInitialize( memPadByteCnt, memAlignByteCnt, memFlags, &ctx.rpt ) != kOkMmRC )
|
||||
{
|
||||
cmErrMsg(&ctx.err,kMemFailAppRC,"Heap initialization failed.");
|
||||
goto errLabel;
|
||||
}
|
||||
|
||||
// initialize the file system
|
||||
if( cmFsInitialize( &ctx, appPrefDir ) != kOkFsRC )
|
||||
cmErrMsg(&ctx.err,kFileSysFailAppRC,"File system initialization failed.");
|
||||
|
||||
// initialize the text system
|
||||
if( cmTsInitialize(&ctx) != kOkTxRC )
|
||||
cmErrMsg(&ctx.err,kTextSysFailAppRC,"Text system initialization failed.");
|
||||
|
||||
// create the print queue
|
||||
if( cmTsMp1cCreate( &printqH, 8192, print_queue_cb, NULL, NULL ) != kOkThRC )
|
||||
cmErrMsg(&ctx.err,kQueueFailAppRC,"Print queue creation failed.");
|
||||
|
||||
|
||||
if( cmErrLastRC(&ctx.err) == kOkAppRC )
|
||||
{
|
||||
app proj(&ctx, printqH, appWndW, appWndH, appTitle, argc, argv);
|
||||
Fl::run();
|
||||
|
||||
// reset the pgm context and print queue console output to stdout
|
||||
cmRptSetup(&ctx.rpt,print,print,NULL);
|
||||
cmTsMp1cSetCbFunc(printqH, print_queue_cb, NULL );
|
||||
}
|
||||
|
||||
// empty any pending text to stdout
|
||||
while( cmTsMp1cMsgWaiting(printqH) )
|
||||
if( cmTsMp1cDequeueMsg(printqH, NULL, 0) != kOkThRC )
|
||||
cmErrMsg(&ctx.err,kQueueFailAppRC,"Print dequeue failed.");
|
||||
|
||||
// destroy the print queue
|
||||
if( cmTsMp1cDestroy(&printqH) != kOkThRC )
|
||||
cmErrMsg(&ctx.err,kQueueFailAppRC,"Print queue destroy failed.");
|
||||
|
||||
// finalize the text system
|
||||
if( cmTsFinalize() != kOkTxRC )
|
||||
cmErrMsg(&ctx.err,kTextSysFailAppRC,"Text system finalization failed.");
|
||||
|
||||
// finalize the file system
|
||||
if( cmFsFinalize() != kOkFsRC )
|
||||
cmErrMsg(&ctx.err,kFileSysFailAppRC,"File system finalize failed.");
|
||||
|
||||
// report memory mgr errors
|
||||
if( cmMdIsValid() )
|
||||
cmMdReport( kIgnoreNormalMmFl );
|
||||
|
||||
// finalize the memory manager
|
||||
if( cmMdFinalize() != kOkMmRC )
|
||||
cmErrMsg(&ctx.err,kMemFailAppRC,"Heap finalization failed.");
|
||||
|
||||
errLabel:
|
||||
|
||||
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
#include "cmPrefix.h"
|
||||
#include "cmGlobal.h"
|
||||
#include "cmRpt.h"
|
||||
#include "cmErr.h"
|
||||
#include "cmCtx.h"
|
||||
#include "cmMem.h"
|
||||
#include "cmMallocDebug.h"
|
||||
#include "cmLinkedHeap.h"
|
||||
#include "cmFileSys.h"
|
||||
#include "cmText.h"
|
||||
|
||||
void print( void* arg, const char* text )
|
||||
{
|
||||
printf("%s\n",text);
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
// initialize the heap check library
|
||||
bool memDebugFl = cmDEBUG_FL;
|
||||
unsigned memGuardByteCnt = memDebugFl ? 8 : 0;
|
||||
unsigned memAlignByteCnt = 16;
|
||||
unsigned memFlags = memDebugFl ? kTrackMmFl | kDeferFreeMmFl | kFillUninitMmFl : 0;
|
||||
|
||||
cmCtx_t ctx;
|
||||
cmCtxSetup(&ctx,"cm test",print,print,NULL,memGuardByteCnt,memAlignByteCnt,memFlags);
|
||||
|
||||
cmMdInitialize( memGuardByteCnt, memAlignByteCnt, memFlags, &ctx.rpt );
|
||||
|
||||
cmFsInitialize( &ctx, "cm_test" );
|
||||
|
||||
cmTsInitialize(&ctx );
|
||||
|
||||
cmTsFinalize();
|
||||
cmFsFinalize();
|
||||
cmMdReport( kIgnoreNormalMmFl );
|
||||
cmMdFinalize();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user