Updated graphics output for new java-based display

git-svn-id: https://tesseract-ocr.googlecode.com/svn/trunk@149 d0cd1f9f-072b-0410-8dd7-cf729c803f20
This commit is contained in:
theraysmith 2008-02-01 00:50:56 +00:00
parent 89a5284c69
commit 1a23b25eeb
22 changed files with 2055 additions and 3561 deletions

View File

@ -1,10 +1,9 @@
SUBDIRS =
AM_CPPFLAGS = -I$(top_srcdir)/image -I$(top_srcdir)/ccutil
AM_CPPFLAGS =
include_HEADERS = \
evntlst.h evnts.h grphics.h grphshm.h sbgconst.h sbgdefs.h \
sbgtypes.h showim.h
scrollview.h svmnode.h svutil.h svpaint.cpp
lib_LIBRARIES = libtesseract_viewer.a
libtesseract_viewer_a_SOURCES = \
evntlst.cpp grphics.cpp evnts.cpp showim.cpp grphshm.cpp
scrollview.cpp svmnode.cpp svutil.cpp

View File

@ -75,13 +75,13 @@ RANLIB = @RANLIB@
VERSION = @VERSION@
SUBDIRS =
AM_CPPFLAGS = -I$(top_srcdir)/image -I$(top_srcdir)/ccutil
AM_CPPFLAGS =
include_HEADERS = evntlst.h evnts.h grphics.h grphshm.h sbgconst.h sbgdefs.h sbgtypes.h showim.h
include_HEADERS = scrollview.h svmnode.h svutil.h svpaint.cpp
lib_LIBRARIES = libtesseract_viewer.a
libtesseract_viewer_a_SOURCES = evntlst.cpp grphics.cpp evnts.cpp showim.cpp grphshm.cpp
libtesseract_viewer_a_SOURCES = scrollview.cpp svmnode.cpp svutil.cpp
mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
CONFIG_HEADER = ../config_auto.h
@ -94,8 +94,7 @@ CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libtesseract_viewer_a_LIBADD =
libtesseract_viewer_a_OBJECTS = evntlst.o grphics.o evnts.o showim.o \
grphshm.o
libtesseract_viewer_a_OBJECTS = scrollview.o svmnode.o svutil.o
AR = ar
CXXFLAGS = @CXXFLAGS@
CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@ -110,8 +109,7 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
DEP_FILES = .deps/evntlst.P .deps/evnts.P .deps/grphics.P \
.deps/grphshm.P .deps/showim.P
DEP_FILES = .deps/scrollview.P .deps/svmnode.P .deps/svutil.P
SOURCES = $(libtesseract_viewer_a_SOURCES)
OBJECTS = $(libtesseract_viewer_a_OBJECTS)

View File

@ -1,344 +0,0 @@
/**********************************************************************
* File: evntlst.c (Formerly eventlst.c)
* Description: Code to manipulate lists of events.
* Author: Ray Smith
* Created: Fri Nov 01 11:02:52 GMT 1991
*
* (C) Copyright 1991, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#include "mfcpch.h"
#include "grphshm.h"
#include "grphics.h"
#ifdef __UNIX__
#include <unistd.h>
#include <signal.h>
//#include "pipes.h"
#include "fileerr.h"
//#include "sbderrs.h"
//#include "grpherr.h"
#elif defined (__MSW32__)
#include <io.h>
#include <process.h>
#else
#include <unistd.h>
#endif
#include "evntlst.h"
#define EXTERN
//anything new in queue
EXTERN BOOL8 event_waiting = FALSE;
#ifdef __UNIX__
//semaphore count
static INT32 event_critical_section = 0;
//true if pending
static BOOL8 event_pending = FALSE;
EXTERN BOOL8 handler_set; //true if signal handler on
EXTERN STRING_VAR (events_logfile, "", "File to log events to");
EXTERN STRING_VAR (events_playback, "", "File to read events from");
/**********************************************************************
* event_handler
*
* Handler for signal.
* If not critical, read events now, otherwise, set pending flag.
**********************************************************************/
void event_handler( //signal handler
int, //signal
int, //code
struct sigcontext *scp //info for sigvector
) {
// scp->sc_syscall_action=SIG_RESTART; //restart sys calls
event_pending = TRUE;
if (!event_critical_section) {
lock_events();
unlock_events();
}
}
/**********************************************************************
* check_event
*
* See if any events are available, and if there are, return 1, else 0.
**********************************************************************/
BOOL8 check_event( /*test for event */
INT16 fd, /*window to wait on */
BOOL8 wait /*set if waiting */
) {
GRAPHICS_EVENT event; /*event from daemon */
SBD_GRAPHICS_EVENT sbd_event; //event from pipe
BOOL8 gotone; /*repeat while do */
INT32 time; /*time to select */
INT32 typein; //input type
INT32 keyin; //input key
INT32 fdin; //input fd
int scanresult; //of fscanf
static FILE *eventsin = NULL; //input file
// && sbfds[fd].used!=1)
if (fd < 0 || fd > maxsbfd || fd > 0) {
// BADSBFD.error("check_event",TESSLOG,NULL); /*report error*/
return FALSE;
}
time = wait ? AWAIT_TIME : CHECK_TIME;
gotone = FALSE;
while (!gotone
&& (events_playback.string ()[0] != '\0' || eventsin != NULL)) {
if (eventsin == NULL && events_playback.string ()[0] != '\0') {
if ((eventsin = fopen (events_playback.string (), "r")) == NULL)
CANTOPENFILE.error ("check_event", TESSLOG,
events_playback.string ());
//remove name
events_playback.set_value (NULL);
}
if (eventsin != NULL) {
scanresult =
fscanf (eventsin,
INT32FORMAT " " INT32FORMAT "(%f,%f) on " INT32FORMAT,
&typein, &keyin, &event.x, &event.y, &fdin);
if (scanresult != 5) {
if (scanresult == EOF)
fprintf (stderr, "Closing input event file\n");
else
fprintf (stderr, "Error on event input: copied %d values\n",
scanresult);
fclose(eventsin);
eventsin = NULL;
}
else {
// fprintf(stderr,"Read input on %d\n", fdin );
event.type = (INT8) typein;
event.key = (char) keyin;
event.fildes = fdin;
add_event(&event); //got one
gotone = gotone || fd == 0 || fd == event.fildes;
/*know if we got one */
}
}
}
while (!gotone) { // && select_read(shminfo.fds[INFD],time)!=0) /*event available*/
if (read (shminfo.fds[INFD], &sbd_event, sizeof (SBD_GRAPHICS_EVENT))
!= sizeof (SBD_GRAPHICS_EVENT))
READFAILED.error ("check_event", EXIT, "sbdaemon pipe");
if (sbd_event.type != QUEUE_CLEAR) {
event.fildes = sbd_event.fd;
event.type = sbd_event.type;
event.key = sbd_event.key;
event.x = sbd_event.x;
event.y = sbd_event.y;
event.next = NULL;
add_event(&event); /*add event to queue */
/*know if we got one */
gotone = gotone || fd == 0 || fd == event.fildes;
}
else
kick_daemon(COUNT_READS); /*keep count accurate */
time = CHECK_TIME;
}
return gotone;
}
#else
EXTERN HANDLE event_sem = NULL; //event lock
/**********************************************************************
* event_reader
*
* A separate thread that reads the input from the pipe and places
* events in the appropriate queue. This thread also calls any appropriate
* event handler on receiving an event.
**********************************************************************/
void event_reader( /*read events */
void *param /*file descriptor */
) {
#ifndef __MAC__
//real file descriptor
HANDLE *fdptr = (HANDLE *) param;
HANDLE fd = *fdptr; //real file descriptor
unsigned long nread; //bytes read
SBD_GRAPHICS_EVENT event; /*event from daemon */
GRAPHICS_EVENT real_event; //converted format
char pipe_char[2]; //from pipe
INT32 pipe_index; //index to event queue
event_id = GetCurrentThreadId ();
while (ReadFile (fd, pipe_char, 2, &nread, NULL) != 0 && nread == 2) {
pipe_index = EVENT_HEAD;
event = EVENT_INDEX (pipe_index);
pipe_index++;
if (pipe_index >= EVENTSIZE)
pipe_index = 0;
EVENT_HEAD = pipe_index;
if (event.type != QUEUE_CLEAR) {
real_event.fildes = event.fd;
real_event.type = event.type;
real_event.key = event.key;
real_event.x = event.x;
real_event.y = event.y;
real_event.next = NULL;
add_event(&real_event); /*add event to queue */
}
else
kick_daemon(COUNT_READS); /*got acknowledge */
}
CloseHandle(fd);
*fdptr = NULL;
_endthread();
#endif
}
#endif
/**********************************************************************
* add_event
*
* Adds an event from the sbdaemon to the correct event queue.
**********************************************************************/
void add_event( /*add an event */
GRAPHICS_EVENT *event /*event to add */
) {
GRAPHICS_EVENT *newevent; /*new event */
EVENT_HANDLER handler; //avoid race hazards
GRAPHICS_EVENT sel_event; //selection
//last button down
static GRAPHICS_EVENT last_down;
#ifdef __UNIX__
static FILE *eventsout = NULL; //output file
static STRING outname; //output name
//doing anything
if (events_logfile.string ()[0] != '\0' || eventsout != NULL) {
if (eventsout != NULL //already open
&& outname != (STRING &) events_logfile) {
fclose(eventsout); //finished that one
eventsout = NULL;
}
//needs opening
if (eventsout == NULL && events_logfile.string ()[0] != '\0') {
//save name
outname = events_logfile.string ();
if ((eventsout = fopen (outname.string (), "w")) == NULL)
CANTOPENFILE.error ("add_event", TESSLOG, outname.string ());
}
if (eventsout != NULL)
fprintf (eventsout, "%d %d(%f,%f) on %d\n",
event->type, event->key, event->x, event->y, event->fildes);
}
#endif
// fprintf(stderr,"Received event of type %d at (%f,%f) on %d\n",
// event->type,event->x,event->y,event->fildes);
event->fd = &sbfds[event->fildes];
switch (event->type) {
case DOWN_EVENT:
last_down = *event; //save it
handler = sbfds[event->fildes].click_handler;
if (handler != NULL) {
(*handler) (event);
return; //done it
}
break;
case UP_EVENT:
sel_event = *event;
if (last_down.x > event->x)
sel_event.xmax = last_down.x;
else {
sel_event.xmax = event->x;
sel_event.x = last_down.x;
}
if (last_down.y > event->y)
sel_event.ymax = last_down.y;
else {
sel_event.ymax = event->y;
sel_event.y = last_down.y;
}
handler = sbfds[event->fildes].selection_handler;
if (handler != NULL) {
(*handler) (&sel_event);
return; //done it
}
break;
case KEYPRESS_EVENT:
handler = sbfds[event->fildes].key_handler;
if (handler != NULL) {
(*handler) (event);
return; //done it
}
break;
case DESTROY_EVENT:
handler = sbfds[event->fildes].destroy_handler;
if (handler != NULL) {
(*handler) (event);
// return; //done it
}
break;
}
lock_events();
newevent = new GRAPHICS_EVENT;
if (newevent != NULL) {
*newevent = *event; /*copy event */
/*first event */
if (sbfds[event->fildes].events == NULL)
sbfds[event->fildes].events = newevent;
else
/*add to end */
sbfds[event->fildes].lastevent->next = newevent;
/*is new end */
sbfds[event->fildes].lastevent = newevent;
newevent->next = NULL;
}
event_waiting = TRUE; //added to queue
unlock_events();
}
/**********************************************************************
* lock_events
*
* Lock out event handler to protect data structures.
**********************************************************************/
void lock_events() { //lock
#ifdef __UNIX__
event_critical_section++;
#elif defined (__MSW32__)
WaitForSingleObject (event_sem, (unsigned long) -1);
#endif
}
/**********************************************************************
* unlock_events
*
* Unlock. If event pending deal with it.
**********************************************************************/
void unlock_events() { //lock
#ifdef __UNIX__
if (event_pending && event_critical_section == 1) {
//get all events
while (check_event (0, FALSE));
event_pending = FALSE;
}
event_critical_section--;
#elif defined (__MSW32__)
//release it
ReleaseSemaphore (event_sem, 1, NULL);
#endif
}

View File

@ -1,51 +0,0 @@
/**********************************************************************
* File: evntlst.h (Formerly eventlst.h)
* Description: Code to manipulate lists of events.
* Author: Ray Smith
* Created: Fri Nov 01 11:02:52 GMT 1991
*
* (C) Copyright 1991, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#ifndef EVNTLST_H
#define EVNTLST_H
#include "sbgtypes.h"
extern BOOL8 event_waiting; //anything new in queue
#ifdef __UNIX__
#include "varable.h"
extern BOOL8 handler_set; //true if signal handler on
extern STRING_VAR_H (events_logfile, "", "File to log events to");
extern STRING_VAR_H (events_playback, "", "File to read events from");
void event_handler( //signal handler
int, //signal
int, //code
struct sigcontext *scp //info for sigvector
);
BOOL8 check_event( /*test for event */
INT16 fd, /*window to wait on */
BOOL8 wait /*set if waiting */
);
#else /* */
extern HANDLE event_sem; //event lock
void event_reader( /*read events */
void *param /*file descriptor */
);
#endif
void add_event( /*add an event */
GRAPHICS_EVENT *event /*event to add */
);
void lock_events(); //lock
void unlock_events(); //lock
#endif

View File

@ -1,349 +0,0 @@
/**********************************************************************
* File: evnts.c (Formerly events.c)
* Description: Additional functions needed to receive graphics events.
* Author: Ray Smith
* Created: Thu May 24 14:13:00 BST 1990
*
* (C) Copyright 1990, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#include "mfcpch.h"
#ifdef __UNIX__
#include "sbderrs.h"
#include "fileerr.h"
#include "grpherr.h"
#endif
#include "grphshm.h"
#include "evntlst.h"
#include "evnts.h"
#define EXTERN
DLLSYM EVENT_HANDLER win_selection_handler;
WINDOW (*await_event_func) (WINDOW, BOOL8, INT8, GRAPHICS_EVENT *) =
def_await_event;
//local non-public functions
GRAPHICS_EVENT *find_event( /*wait for event */
INT16 &fd, /*window to wait on */
BOOL8 wait, /*waiting flag */
INT8 event_type /*type to look for */
);
/*search for event */
GRAPHICS_EVENT *search_event_queue(INT16 &fd, /*queue to search */
INT8 event_type /*type to search for */
);
/*search for event */
GRAPHICS_EVENT *search_single_queue(INT16 fd, /*queue to search */
INT8 event_type /*type to search for */
);
/**********************************************************************
* await_selection
*
* Wait (or check) for a selection on the given (or all) fd and return it.
**********************************************************************/
DLLSYM WINDOW await_selection( /*wait for selection */
WINDOW win, /*window to wait on */
BOOL8 wait, /*waiting flag */
float &xmin, /*coords of selection */
float &ymin, /*coords of selection */
float &xmax, /*coords of selection */
float &ymax /*coords of selection */
) {
GRAPHICS_EVENT event; /*return event */
win = await_event (win, wait, SELECT_EVENT, &event);
if (event.type == DESTROY_EVENT)
return NULL; //was destroyed
if (win != NULL) {
xmin = event.x; /*get coords */
ymin = event.y;
xmax = event.xmax; /*get coords */
ymax = event.ymax;
}
return win;
}
/**********************************************************************
* await_click
*
* Wait (or check) for a click on the given (or all) fd and return it.
**********************************************************************/
DLLSYM WINDOW await_click( /*wait for click */
WINDOW win, /*window to wait on */
BOOL8 wait, /*waiting flag */
float &x, /*coords of click */
float &y /*coords of click */
) {
GRAPHICS_EVENT event; /*return event */
win = await_event (win, wait, DOWN_EVENT, &event);
if (event.type == DESTROY_EVENT)
return NULL; //was destroyed
if (win != NULL) {
x = event.x; /*get coords */
y = event.y;
}
return win;
}
/**********************************************************************
* await_key
*
* Wait (or check) for a key on the given (or all) fd and return it.
**********************************************************************/
DLLSYM WINDOW await_key( /*wait for key */
WINDOW win, /*window to wait on */
BOOL8 wait, /*waiting flag */
char &c /*return character */
) {
GRAPHICS_EVENT event; /*return event */
win = await_event (win, wait, KEYPRESS_EVENT, &event);
if (event.type == DESTROY_EVENT)
return NULL; //was destroyed
if (win != NULL)
c = event.key; /*get keypress */
return win;
}
/**********************************************************************
* await_event
*
* Wait (or check) for a event on the given (or all) fd and return it.
**********************************************************************/
DLLSYM WINDOW def_await_event( /*wait for event */
WINDOW win, /*window to wait on */
BOOL8 wait, /*waiting flag */
INT8 event_type, /*type to wait for */
GRAPHICS_EVENT *out_event /*output event */
) {
GRAPHICS_EVENT *event; /*return event */
INT16 fd; //file descriptor
if (win == NULL)
fd = 0;
else
fd = win->get_fd ();
/*look for one */
event = find_event (fd, wait, event_type);
if (event == NULL)
return NULL; /*not found */
else {
*out_event = *event; /*copy event */
if (event->type != DESTROY_EVENT)
delete event; //free the element
return out_event->fd;
}
}
/**********************************************************************
* find_event
*
* Search the queue for an event of a given type, and return it.
* Read or wait until one turns up if there is not one already.
**********************************************************************/
GRAPHICS_EVENT *find_event( /*wait for event */
INT16 &fd, /*window to wait on */
BOOL8 wait, /*waiting flag */
INT8 event_type /*type to look for */
) {
GRAPHICS_EVENT *event; /*return event */
/*look for one */
event = search_event_queue (fd, event_type);
if (event == NULL) {
do {
#ifdef __UNIX__
if (check_event (fd, wait))
#elif defined (__MSW32__)
if (wait)
Sleep (50);
if (event_waiting)
#endif
{
// fprintf(stderr,"Got an event:searching queue %d\n",fd);
/*try after reading */
event = search_event_queue (fd, event_type);
}
}
while (wait && event == NULL);
}
// if (event!=NULL)
// event->fd=&sbfds[fd];
return event; /*event located */
}
/**********************************************************************
* search_event_queue
*
* Search the event queue(s) for events of a particular type.
* If found, it is removed from the queue and returned.
**********************************************************************/
GRAPHICS_EVENT *search_event_queue( /*search for event */
INT16 &fd, /*queue to search */
INT8 event_type /*type to search for */
) {
GRAPHICS_EVENT *event; /*event from daemon */
INT16 testfd; /*test window */
if (fd < 0 || fd > maxsbfd || fd > 0 && sbfds[fd].used != 1) {
return NULL;
}
if (fd > 0)
/*just one to search */
return search_single_queue (fd, event_type);
else {
for (testfd = 1; testfd < maxsbfd; testfd++) {
if (sbfds[testfd].used) {
event = search_single_queue (testfd, event_type);
if (event != NULL) {
fd = testfd; /*successful window */
return event; /*got one */
}
}
}
}
return NULL; /*found nothing */
}
/**********************************************************************
* search_single_queue
*
* Search the event queue for events of a particular type.
* If found, it is removed from the queue and returned.
**********************************************************************/
GRAPHICS_EVENT *search_single_queue( /*search for event */
INT16 fd, /*queue to search */
INT8 event_type /*type to search for */
) {
GRAPHICS_EVENT *event; /*event from daemon */
GRAPHICS_EVENT *prev; /*previous event */
GRAPHICS_EVENT *event2; /*2nd event */
GRAPHICS_EVENT *prev2; /*2nd previous */
GRAPHICS_EVENT *nextevent; /*next event in list */
BOOL8 any_destroy = FALSE;
lock_events();
event_waiting = FALSE; //done a scan
prev = NULL; /*previous event */
event2 = NULL; /*2nd event */
if (event_type == ANY_EVENT) {
event = sbfds[fd].events; /*start of queue */
}
else if (event_type == SELECT_EVENT) {
for (prev = NULL, event = sbfds[fd].events; event != NULL
&& event->type != DOWN_EVENT; event = nextevent) {
//Delete up events that are in the list prior to a down event
nextevent = event->next; /*next in list */
if (event->type == UP_EVENT) {
if (prev == NULL)
/*new head */
sbfds[fd].events = nextevent;
else
prev->next = nextevent;/*delete event */
if (nextevent == NULL)
/*new last element */
sbfds[fd].lastevent = prev;
delete event;
}
else
prev = event;
if (event->type == DESTROY_EVENT)
any_destroy = TRUE;
}
if (event == NULL) {
unlock_events();
if (any_destroy)
return search_single_queue (fd, DESTROY_EVENT);
return NULL; /*no good */
}
for (prev2 = event, event2 = event->next; event2 != NULL
&& event2->type != UP_EVENT;
prev2 = event2, event2 = event2->next);
if (event2 == NULL) {
unlock_events();
return NULL; /*no good */
}
if (prev2 != event) { /*got some intervening */
for (prev2 = event->next; prev2 != event2; prev2 = nextevent) {
nextevent = prev2->next;
delete prev2;
}
}
event->next = event2->next; /*cut out event2 */
event2->next = NULL; /*event is new end */
event->xmax = event2->x; /*get coords */
event->ymax = event2->y;
if (event->x > event->xmax) {
event->xmax = event->x;
event->x = event2->x; /*get coords */
}
if (event->y > event->ymax) {
event->ymax = event->y;
event->y = event2->y;
}
delete event2; //free the element
}
else {
for (prev = NULL, event = sbfds[fd].events; event != NULL
&& event->type != DESTROY_EVENT
&& event->type != event_type; event = nextevent) {
nextevent = event->next; /*next in list */
/*delete up in front of down */
if (event->type == UP_EVENT && event_type == DOWN_EVENT) {
if (prev == NULL)
/*new head */
sbfds[fd].events = nextevent;
else
prev->next = nextevent;/*delete event */
if (nextevent == NULL)
/*new last element */
sbfds[fd].lastevent = prev;
delete event;
}
else
prev = event; /*trailing ptr */
}
}
if (event == NULL) {
unlock_events();
return NULL; /*no good */
}
if (event->type != DESTROY_EVENT) {
if (prev == NULL)
/*new head */
sbfds[fd].events = event->next;
else
prev->next = event->next; /*delete event */
if (event->next == NULL)
sbfds[fd].lastevent = prev;/*new last event */
event->next = NULL; /*possible 2nd event */
}
unlock_events();
return event; /*got one!! */
}

View File

@ -1,52 +0,0 @@
/**********************************************************************
* File: evnts.h (Formerly events.h)
* Description: Header of functions and types needed for using events.
* Author: Ray Smith
* Created: Thu May 24 15:14:45 BST 1990
*
* (C) Copyright 1990, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#ifndef EVNTS_H
#define EVNTS_H
#include "grphics.h"
extern DLLSYM EVENT_HANDLER win_selection_handler;
DLLSYM WINDOW await_selection( /*wait for selection */
WINDOW win, /*window to wait on */
BOOL8 wait, /*waiting flag */
float &xmin, /*coords of selection */
float &ymin, /*coords of selection */
float &xmax, /*coords of selection */
float &ymax /*coords of selection */
);
DLLSYM WINDOW await_click( /*wait for click */
WINDOW win, /*window to wait on */
BOOL8 wait, /*waiting flag */
float &x, /*coords of click */
float &y /*coords of click */
);
DLLSYM WINDOW await_key( /*wait for key */
WINDOW win, /*window to wait on */
BOOL8 wait, /*waiting flag */
char &c /*return character */
);
DLLSYM WINDOW def_await_event( /*wait for event */
WINDOW win, /*window to wait on */
BOOL8 wait, /*waiting flag */
INT8 event_type, /*type to wait for */
GRAPHICS_EVENT *out_event /*output event */
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,270 +0,0 @@
/**********************************************************************
* File: grphics.h (Formerly graphics.h)
* Description: Starbase stubs for connection to sbdaemon
* Author: Ray Smith
* Created: Wed May 16 08:34:32 BST 1990
*
* (C) Copyright 1990, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#ifndef GRPHICS_H
#define GRPHICS_H
//This is the main include file needed to get sbdaemon functionality
//TO BUILD A PROGRAM THAT USES SBDAEMON, YOU NEED:
//GRPHICS.CPP GRPHSHM.CPP AND EVNTLST.CPP.
//If you want to be able to wait for events, add evnts.cpp and include evnts.h.
//If you want to be able to show images, add showim.cpp and include showim.h.
#include "sbgdefs.h"
#include "sbgconst.h"
#define STATESIZE 13 //MUST equal EDGESTYLE+1
#define line_color_index(fd,index) fd->Line_color_index(index)
#define perimeter_color_index(fd,index) fd->Perimeter_color_index(index)
#define fill_color_index(fd,index) fd->Fill_color_index(index)
#define fill_color(fd,r,g,b) fd->Fill_color(r,g,b)
#define text_color_index(fd,index) fd->Text_color_index(index)
#define text_font_index(fd,index) fd->Text_font_index(index)
#define character_height(fd,height) fd->Character_height(height)
#define line_type(fd,style) fd->Line_type(style)
#define interior_style(fd,style,edged) fd->Interior_style(style,edged)
#define move2d(fd,x,y) fd->Move2d(x,y)
#define draw2d(fd,x,y) fd->Draw2d(x,y)
#define rectangle(fd,x1,y1,x2,y2) fd->Rectangle(x1,y1,x2,y2)
#define text2d(fd,x,y,string,xform,more) fd->Text2d(x,y,string,xform,more)
#define ellipse(fd,x_radius,y_radius,x_center,y_center,rotation) fd->Ellipse(x_radius,y_radius,x_center,y_center,rotation)
#define destroy_window(fd) fd->Destroy_window()
#define clear_view_surface(fd) fd->Clear_view_surface()
#define vdc_extent(fd,xmin,ymin,xmax,ymax) fd->Vdc_extent(xmin,ymin,xmax,ymax)
#define make_picture_current(fd) fd->Make_picture_current()
#define set_click_handler(fd,handler) fd->Set_click_handler(handler)
#define set_selection_handler(fd,handler) fd->Set_selection_handler(handler)
#define set_key_handler(fd,handler) fd->Set_key_handler(handler)
#define set_destroy_handler(fd,handler) fd->Set_destroy_handler(handler)
#define clear_event_queue(fd) fd->Clear_event_queue()
#define create_window(name,window_type,xpos,ypos,xsize,ysize,xmin,xmax,ymin,ymax,downon,moveon,upon,keyon) (*create_func)(name,window_type,xpos,ypos,xsize,ysize,xmin,xmax,ymin,ymax,downon,moveon,upon,keyon)
#define overlap_picture_ops(update) (*overlap_func)(update)
#define await_event(win,wait,type,event) (*await_event_func)(win,wait,type,event)
typedef void (*EVENT_HANDLER) (GRAPHICS_EVENT *);
/*name/title of window */
typedef WINDOW (*WINCREATEFUNC) (const char *name,
INT8 window_type, /*type of window */
INT16 xpos, /*coords of window */
INT16 ypos, /*coords of window */
INT16 xsize, /*size of window */
INT16 ysize, /*size of window */
float xmin, /*scrolling limits */
float xmax, /*to stop users */
float ymin, /*getting lost in */
float ymax, /*empty space */
BOOL8 downon, /*Events wanted */
BOOL8 moveon, BOOL8 upon, BOOL8 keyon);
extern WINCREATEFUNC create_func;
extern void (*overlap_func) (BOOL8);
extern WINDOW (*await_event_func) (WINDOW, BOOL8, INT8, GRAPHICS_EVENT *);
const int kInputSize = 16;
extern int input_unicode[kInputSize];
class DLLSYM WINFD
{
public:
//Constructors for WINFD are host dependent to match different
//implementations and are intended to be called only by
//create_window. Use create_window to make a window.
static WINDOW create( /*create a window */
const char *name, /*name/title of window */
INT8 window_type, /*type of window */
INT16 xpos, /*coords of window */
INT16 ypos, /*coords of window */
INT16 xsize, /*size of window */
INT16 ysize, /*size of window */
float xmin, /*scrolling limits */
float xmax, /*to stop users */
float ymin, /*getting lost in */
float ymax, /*empty space */
BOOL8 downon, /*Events wanted */
BOOL8 moveon,
BOOL8 upon,
BOOL8 keyon);
WINFD(); //constructor
virtual ~ WINFD ();
/*set line colour */
virtual void Line_color_index(COLOUR index); /*index to use */
/*set perimeter colour */
virtual void Perimeter_color_index(COLOUR index); /*index to use */
/*set fill colour */
virtual void Fill_color_index(COLOUR index); /*index to use */
virtual void Fill_color( /*set RGB fill colour */
UINT8 red,
UINT8 green,
UINT8 blue);
/*set marker colour */
virtual void Marker_color_index(COLOUR index); /*index to use */
/*set text colour */
virtual void Text_color_index(COLOUR index); /*index to use */
/*set text font */
virtual void Text_font_index(INT16 index); /*index to use */
/*set text height */
virtual void Character_height(float height); /*height to use */
virtual void Line_type( /*set line type */
INT16 style); /*style to use */
virtual void Marker_type( /*set marker type */
INT16 type); /*type to use */
virtual void Interior_style( /*set polygon style */
INT16 style, /*style to use */
INT16 edged); /*draw edge or not */
virtual void Marker_size( /*set marker size */
float size); /*size to use */
virtual void Move2d( /*move the pen */
float x, /*coords to move to */
float y); /*coords to move to */
virtual void Draw2d( /*draw the pen */
float x, /*coords to draw to */
float y); /*coords to draw to */
virtual void Rectangle( /*draw a rectangle */
float x1, /*coords to draw to */
float y1, /*coords to draw to */
float x2, /*coords to draw to */
float y2); /*coords to draw to */
virtual void Text_alignment( /*draw a rectangle */
INT32 h_select, //horizontal
INT32 v_select, //vertical
float horiz, /*coords to draw to */
float vert); /*coords to draw to */
virtual void Polyline2d ( /*draw a polyline */
float clist[], /*coordinate list */
INT16 numpts, /*number of coords */
INT16 flags); /*does it have move/draws */
virtual void Polygon2d ( /*draw a polygon */
float clist[], /*coordinate list */
INT16 numpts, /*number of coords */
INT16 flags); /*does it have move/draws */
virtual void Polymarker2d ( /*draw a polymarker */
float clist[], /*coordinate list */
INT16 numpts, /*number of coords */
INT16 flags); /*does it have move/draws */
virtual void Text2d( /*draw a text */
float x, /*coords of text */
float y,
const char *string, /*text to draw */
INT16 xform, /*transform */
INT16 more); /*more text? */
void Append_text( /*draw a text */
const char *string, /*text to draw */
INT16 xform, /*transform */
INT16 more); /*more text? */
virtual void Ellipse( /*draw a ellipse */
float x_radius, /*radii of ellipse */
float y_radius, /*radii of ellipse */
float x_center, /*centre of ellipse */
float y_center, /*centre of ellipse */
float rotation); /*rotation of ellipse */
virtual void Arc( /*draw a arc */
float x_radius, /*radii of arc */
float y_radius, /*radii of arc */
float x_center, /*centre of arc */
float y_center, /*centre of arc */
float start, /*ends of arc */
float stop, /*ends of arc */
float rotation, /*rotation of arc */
INT16 close_type); /*type of closure */
/*destroy a window */
virtual void Destroy_window();
/*clear window */
virtual void Clear_view_surface();
/*Mark need to recalc */
virtual void Re_compute_colourmap();
virtual void Vdc_extent( /*set window focus */
float xmin, /*min values */
float ymin, /*min values */
float xmax, /*max values */
float ymax); /*max values */
void Set_echo( /*set window echo */
ECHO_TYPE echo_type, //type of echo
float xorig, /*min values */
float yorig); /*min values */
/*update window */
virtual void Make_picture_current();
/*flush output */
friend void def_overlap_picture_ops(BOOL8 update); /*send make_ */
/*set line colour */
virtual void Synchronize_windows(WINDOW fd2); //other window
/* void Show_sub_image( //show rectangle
IMAGE* source, //source image
INT32 xstart, //start coords
INT32 ystart,
INT32 xext, //extent to copy
INT32 yext,
INT32 xdest, //destination coords
INT32 ydest);*/
INT16 get_fd() { //access
return fd;
}
void Set_selection_handler( //set callback function
EVENT_HANDLER handler); //handler function
void Set_key_handler( //set callback function
EVENT_HANDLER handler); //handler function
void Set_destroy_handler( //set callback function
EVENT_HANDLER handler); //handler function
void Set_click_handler( //set callback function
EVENT_HANDLER handler); //handler function
/*delete all events */
virtual void Clear_event_queue();
//internal maintenance functions
friend void add_event( /*add an event */
GRAPHICS_EVENT *event); /*event to add */
/*search for event */
friend GRAPHICS_EVENT *search_event_queue(INT16 &fd, /*queue to search */
INT8 event_type); /*type to search for */
/*search for event */
friend GRAPHICS_EVENT *search_single_queue(INT16 fd, /*queue to search */
INT8 event_type); /*type to search for */
protected:
EVENT_HANDLER click_handler; //callback function
//callback function
EVENT_HANDLER selection_handler;
EVENT_HANDLER key_handler; //callback function
//callback function
EVENT_HANDLER destroy_handler;
private:
void get_lock() {
} //wait for lock
void get_lock_for_draw() {
} //kill draw thread
void release_lock() {
} //let it go
void get_core_lock() {
} //wait for lock
void release_core_lock() {
} //let it go
INT16 fd; //"file descriptor"
BOOL8 used; /*true if fd in use */
BOOL8 downevent; /*event flags */
BOOL8 moveevent;
BOOL8 upevent;
BOOL8 keyevent;
GRAPHICS_EVENT *events; /*event queue */
GRAPHICS_EVENT *lastevent; /*event queue */
};
#endif

View File

@ -1,472 +0,0 @@
/**********************************************************************
* File: grphshm.c (Formerly graphshm.c)
* Description: Functions for the shared memory sbdaemon connection.
* Author: Ray Smith
* Created: Thu May 24 14:09:38 BST 1990
*
* (C) Copyright 1990, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#include "mfcpch.h"
#include "evntlst.h"
#ifdef __UNIX__
#include <sys/ipc.h>
#include <sys/shm.h>
//#include <osfcn.h>
#include <errno.h>
//#include "pipes.h"
#include "fileerr.h"
//#include "grpherr.h"
//#include "basefile.h"
#include <unistd.h>
#elif defined(__MSW32__)
#include <io.h>
#include <fcntl.h>
#include <process.h>
#include <stdio.h>
#else
#endif
#include <string.h>
#include "grphics.h"
#include "grphshm.h"
#define EXTERN
EXTERN SHMINFO shminfo; /*shared memory */
EXTERN WINFD sbfds[MAXWINDOWS]; /*file descriptors */
EXTERN INT16 maxsbfd = 0; /*no of fds in use */
#ifdef __MSW32__
//event thread id
EXTERN DWORD event_id = (DWORD) - 1;
#endif
/**********************************************************************
* start_sbdaemon
*
* Creates the shared memory segment and starts up the sbdaemon telling
* it info about the segment. This only needs to be called once.
* It is called automatically from create_window at the first creation attempt.
**********************************************************************/
void start_sbdaemon() { /*start the daemon */
#if defined (__UNIX__) || defined(__MSW32__)
char *shmaddr; /*address to attach */
char *sbenv; /*SB_DISPLAY_ADDR */
INT32 sbaddr; /*starbase address */
INT32 wmshm; //windows shared mem
char arg1[MAX_PATH]; /*shmid argument */
char arg2[MAX_PATH]; /*shmstart argument */
char arg3[MAX_PATH]; /*shmsize argument */
const char *argv[5]; /*args of sbdaemon */
/*for pipe usage */
static char pipebuffer[PIPESIZE];
sbenv = getenv (SBADDR); /*get SB_DISPLAY_ADDR */
if (sbenv == NULL || sscanf (sbenv, INT32FORMAT, &sbaddr) != 1)
sbaddr = SBDEFAULT;
shmaddr = getenv (WMSHM);
if (shmaddr == NULL || sscanf (shmaddr, INT32FORMAT, &wmshm) != 1)
wmshm = WMSHMDEFAULT;
/*default address */
shmaddr = (char *) sbaddr - (wmshm + SHMSIZE + SHMOFFSET);
if (!remote_display (arg1)) {
shminfo.shmsize = SHMSIZE; /*size of segment */
#ifdef __UNIX__
shminfo.shmid = shmget (IPC_PRIVATE, SHMSIZE, USER_RW);
/*get shm segment */
// if (shminfo.shmid==-1)
// NO_SHM_SEGMENT.error("start_sbdaemon",ABORT,"Errno=%d",errno);
#ifdef hp9000s800
/*attach it */
shminfo.shmstart = shmat (shminfo.shmid, 0, 0);
if ((int) shminfo.shmstart == -1)
#else
/*attach it */
shminfo.shmstart = shmat (shminfo.shmid, shmaddr, 0);
// if (shminfo.shmstart!=shmaddr)
#endif
// SHM_ATTACH_FAILED.error("start_sbdaemon",ABORT,"Errno=%d",errno);
#else
SECURITY_ATTRIBUTES security;//for handles
security.nLength = sizeof (security);
security.lpSecurityDescriptor = NULL;
//make it inheritable
security.bInheritHandle = TRUE;
//anonymous
shminfo.shmid = CreateFileMapping ((HANDLE) 0xffffffff, &security, PAGE_READWRITE, 0, shminfo.shmsize + 3 * sizeof (INT32) + EVENTSIZE * sizeof (SBD_GRAPHICS_EVENT), NULL);
if (shminfo.shmid == NULL) {
shminfo.shmstart = NULL;
return; //quietly fail
}
shminfo.shmstart =
MapViewOfFile (shminfo.shmid, FILE_MAP_WRITE, 0, 0, 0);
if (shminfo.shmstart == NULL)
return;
EVENT_TAIL = 0;
EVENT_HEAD = 0;
#endif
/*set up args */
sprintf (arg1, "%d", shminfo.shmid);
sprintf (arg2, "%p", shminfo.shmstart);
sprintf (arg3, INT32FORMAT, shminfo.shmsize);
argv[0] = SBDAEMON; /*set up argv */
argv[1] = arg1;
argv[2] = arg2;
argv[3] = arg3;
argv[4] = NULL;
}
else {
shmaddr = NULL; //remote
fprintf (stderr, "start_sbdaemon:using %s to connect to machine %s\n",
REMSH, arg1);
#ifdef __UNIX__
shminfo.shmid = -1;
#else
shminfo.shmid = NULL;
#endif
/*not using shm */
shminfo.shmstart = pipebuffer;
shminfo.shmsize = PIPESIZE; /*size of pipe buffer */
#ifdef __UNIX__
/*command on host */
sprintf (arg2, "%s=0x%x; export %s; %s -1 0 " INT32FORMAT " %s", SBADDR, sbaddr, SBADDR, SBDAEMON, shminfo.shmsize, getenv (DISP));
#else
/*command on host */
sprintf (arg2, "%s -1 0 %d %s", SBDAEMON, shminfo.shmsize, getenv (DISP));
#endif
argv[0] = REMSH; /*set up argv */
argv[1] = arg1; /*host to use */
argv[2] = arg2;
argv[3] = NULL;
}
shminfo.usedsize = 0; /*none used yet */
#ifdef __UNIX__
// shminfo.pid=two_way_pipe(argv[0],argv,shminfo.fds); /*start daemon*/
#else
if (two_way_pipe (argv[0], argv, shminfo.fds) != 0) {
cleanup_sbdaemon();
}
else {
//anonymous
event_sem = CreateSemaphore (NULL, 1, 1, NULL);
//xiaofan
_beginthread (event_reader, 0, &shminfo.fds[INFD]);
}
#endif
#endif
}
/**********************************************************************
* cleanup_sbdaemon
*
* Free system resources for when the daemon has failed or been killed.
**********************************************************************/
void cleanup_sbdaemon() { /*forget about the daemon */
#ifdef __MSW32__
if (shminfo.fds[INFD] != NULL) {
CloseHandle (shminfo.fds[INFD]);
shminfo.fds[INFD] = 0;
}
if (shminfo.fds[OUTFD] != NULL) {
CloseHandle (shminfo.fds[OUTFD]);
shminfo.fds[OUTFD] = 0;
}
if (shminfo.shmstart != NULL) {
UnmapViewOfFile (shminfo.shmstart);
shminfo.shmstart = NULL;
}
if (shminfo.shmid != NULL) {
CloseHandle (shminfo.shmid);
shminfo.shmid = NULL;
}
if (event_sem != NULL) {
CloseHandle(event_sem);
event_sem = NULL;
}
#elif defined(__UNIX__)
if (shminfo.fds[INFD] > 0) {
close (shminfo.fds[INFD]);
shminfo.fds[INFD] = 0;
}
if (shminfo.fds[OUTFD] > 0) {
close (shminfo.fds[OUTFD]);
shminfo.fds[OUTFD] = 0;
}
shminfo.shmstart = NULL;
#endif
}
/**********************************************************************
* remote_display
*
* Returns TRUE if the DISPLAY environment variable points to a
* Remote display, and sets the name to the name of the host.
* Otherwise, returns FALSE.
**********************************************************************/
BOOL8 remote_display( //check for remote
char *name //name of host
) {
#if defined (__UNIX__) || defined(__MSW32__)
char *xenv; /*DISPLAY environ */
char *nameend; //end of name
#ifdef __UNIX__
char thishost[MAX_PATH]; //current host
#endif
xenv = getenv (DISP); /*get display variable */
if (xenv != NULL) {
strcpy(name, xenv);
nameend = strchr (name, ':');
if (nameend != NULL)
*nameend = '\0'; /*chop display off */
nameend = strchr (name, '.');
if (nameend != NULL)
*nameend = '\0'; /*chop resolv off */
#ifdef __UNIX__
if (strcmp (name, LOCAL1) && strcmp (name, LOCAL2)
&& gethostname (thishost, MAX_PATH) >= 0) {
nameend = strchr (thishost, '.');
if (nameend != NULL)
*nameend = '\0'; /*chop resolv off */
if (strcmp (name, thishost)) {
return TRUE;
}
}
#else
return TRUE;
#endif
}
#endif
return FALSE;
}
/**********************************************************************
* getshm
*
* Get the next element of the shared memory. If there is no more room
* in the segment, kick the daemon to get it to empty it out and then
* restart the buffer once it acknowledges the cleanout.
**********************************************************************/
DLLSYM void *getshm( /*get memory */
INT32 size /*required size */
) {
void *segment; /*return segment */
if (shminfo.shmstart == NULL)
return NULL; //no daemon connection
size = (size + 3) & ~3;
if (size > shminfo.shmsize)
return NULL;
/*too full? */
if (shminfo.usedsize + size > shminfo.shmsize
|| shminfo.usedsize < 0) { /*or read pending */
kick_daemon(AWAIT_BUFFER); /*get it to read */
}
/*address of segment */
segment = (char *) shminfo.shmstart + shminfo.usedsize;
shminfo.usedsize += size; /*sum used sizes */
return segment;
}
/**********************************************************************
* kick_daemon
*
* Tell the daemon to read the shared memory and perform all the
* operations in it. This function blocks until the daemon has
* emptied the queue.
**********************************************************************/
void kick_daemon( /*empty queue */
INT8 mode /*control mode */
) {
#ifndef __MAC__
SBD_GRAPHICS_EVENT event; /*event from daemon */
GRAPHICS_EVENT real_event; //converted format
#ifdef __MSW32__
unsigned long nwrite;
unsigned long nread; //bytes read
char pipe_char[2]; //char from pipe
INT32 pipe_index; //index to event queue
#endif
static INT16 reads_pending = 0;/*acknowledges pending */
if (mode == COUNT_READS) {
lock_events();
reads_pending--; /*got a read */
unlock_events();
return;
}
if (shminfo.shmstart == NULL)
return; //no connection
if (shminfo.usedsize > 0) {
#ifdef __UNIX__
if (write
(shminfo.fds[OUTFD], (const char *) &shminfo.usedsize,
sizeof (INT32)) != sizeof (INT32))
WRITEFAILED.error ("kick_daemon", EXIT, "sbdaemon pipe");
#else
PRIMITIVES = shminfo.usedsize;
if (WriteFile (shminfo.fds[OUTFD], "xx", 2, &nwrite, NULL) == 0
|| nwrite != 2) {
cleanup_sbdaemon();
return;
}
#endif
#ifdef __UNIX__
if (shminfo.shmid < 0) {
if (write (shminfo.fds[OUTFD], (const char *) shminfo.shmstart,
shminfo.usedsize) != shminfo.usedsize)
WRITEFAILED.error ("kick_daemon", EXIT, "sbdaemon pipe");
#else
if (shminfo.shmid == NULL) {
if (WriteFile (shminfo.fds[OUTFD], (const char *) shminfo.shmstart,
shminfo.usedsize, &nwrite, NULL) == 0
|| nwrite != (UINT32) shminfo.usedsize) {
cleanup_sbdaemon();
return;
}
#endif
shminfo.usedsize = 0; /*can use it now */
}
else
shminfo.usedsize = -1; /*need to wait */
lock_events();
reads_pending++; /*acknowledges due */
unlock_events();
}
if (mode == FLUSH_IN || reads_pending > MAX_PENDING || mode == AWAIT_BUFFER
#ifdef __UNIX__
&& shminfo.shmid < 0)
#else
&& shminfo.shmid != NULL)
#endif
{
while (reads_pending > 0) {
#ifdef __MSW32__
if (event_id == GetCurrentThreadId ()) {
if (ReadFile (shminfo.fds[INFD], pipe_char, 2, &nread, NULL) != 0
&& nread == 2) {
pipe_index = EVENT_HEAD;
event = EVENT_INDEX (pipe_index);
pipe_index++;
if (pipe_index >= EVENTSIZE)
pipe_index = 0;
EVENT_HEAD = pipe_index;
#endif
#ifdef __UNIX__
if (read
(shminfo.fds[INFD], &event,
sizeof (SBD_GRAPHICS_EVENT)) !=
sizeof (SBD_GRAPHICS_EVENT))
READFAILED.error ("kick_daemon", EXIT, "sbdaemon pipe");
#endif
if (event.type != QUEUE_CLEAR) {
real_event.fildes = event.fd;
real_event.type = event.type;
real_event.key = event.key;
real_event.x = event.x;
real_event.y = event.y;
real_event.next = NULL;
/*add event to queue */
add_event(&real_event);
}
else
reads_pending--; /*got acknowledge */
#ifdef __MSW32__
}
}
else
Sleep (50);
#endif
}
if (shminfo.usedsize < 0) //must be reentrant
shminfo.usedsize = 0; /*none used now */
}
#endif
}
#ifdef __MSW32__
/**********************************************************************
* two_way_pipe
*
* Open the process and connect a 2 way pipe to its stdin and stdout.
**********************************************************************/
int
two_way_pipe ( //do one file
const char *file, //program to run
const char *argv[], //args to execvp
HANDLE fds[] //output fds
) {
int argind; //argument index
HANDLE infds[2]; //input fds
HANDLE outfds[2]; //output fds
HANDLE sends[2]; //fds for child
HANDLE process; //current process
STARTUPINFO start_info; //start information
//process info
PROCESS_INFORMATION proc_info;
char cmd[MAX_PATH * 2]; //final command line
if (CreatePipe (&infds[0], &infds[1], NULL, PIPESIZE) == 0
|| CreatePipe (&outfds[0], &outfds[1], NULL, PIPESIZE) == 0)
return -1;
/* if (_pipe(infds,PIPESIZE,_O_BINARY)<0
|| _pipe(outfds,PIPESIZE,_O_BINARY)<0)
return -1; */
process = GetCurrentProcess ();
if (DuplicateHandle (process, outfds[0],
process, &sends[0], GENERIC_READ, TRUE,
DUPLICATE_CLOSE_SOURCE) == 0)
return -1;
if (DuplicateHandle (process, infds[1],
process, &sends[1], GENERIC_WRITE, TRUE,
DUPLICATE_CLOSE_SOURCE) == 0)
return -1;
cmd[0] = '\0';
for (argind = 0; argv[argind] != NULL; argind++) {
if (argind != 0)
strcat (cmd, " ");
strcat (cmd, argv[argind]);
}
GetStartupInfo(&start_info);
start_info.wShowWindow = FALSE;
start_info.hStdInput = sends[0];
start_info.hStdOutput = sends[1];
start_info.dwFlags = STARTF_USESTDHANDLES;
if (!CreateProcess (NULL, (char *) cmd, NULL, NULL, TRUE,
CREATE_NO_WINDOW | CREATE_SUSPENDED, NULL, NULL,
&start_info, &proc_info))
return -1;
CloseHandle (sends[0]);
CloseHandle (sends[1]);
CloseHandle (proc_info.hProcess);
ResumeThread (proc_info.hThread);
CloseHandle (proc_info.hThread);
fds[INFD] = infds[0];
fds[OUTFD] = outfds[1];
return 0;
}
#endif

View File

@ -1,74 +0,0 @@
/**********************************************************************
* File: grphshm.h (Formerly graphshm.h)
* Description: Header for graphics shared memory functions.
* Author: Ray Smith
* Created: Thu May 24 15:29:28 BST 1990
*
* (C) Copyright 1990, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#ifndef GRPHSHM_H
#define GRPHSHM_H
#include "sbgtypes.h"
#include "grphics.h"
#define SHMSIZE (65536*8) /*shm segment size */
#define PIPESIZE 8192 /*pipe bufer size */
#define USER_RW 0600 /*permission flags */
/*starbase environ */
#define SBADDR "SB_DISPLAY_ADDR"
#define WMSHM "WMSHMSPC" /*shared mem size */
#define WMSHMDEFAULT 0x200000 /*default value */
#define SBDEFAULT 0x0b00000 /*default ADDR */
#define SHMOFFSET 0x200000 /*offset before sbaddr */
#define MAXDATA 0x1000000 /*default data seg size */
#define SBDAEMON "sbdaemon"
#define REMSH "remsh" /*command for remote use */
#define DISP "DISPLAY" /*environ var */
#define LOCAL1 "local" /*possible values */
#define LOCAL2 "unix" /*of DISPLAY */
#define FLUSH_OUT 0 /*kick_daemon commands */
#define FLUSH_IN 1
#define AWAIT_BUFFER 2 /*wait for free buffer */
#define COUNT_READS 3 /*count a queue clear */
#define MAX_PENDING 255 /*max pending reads */
extern SHMINFO shminfo; /*shared memory */
extern WINFD sbfds[MAXWINDOWS]; /*file descriptors */
extern INT16 maxsbfd;
#ifdef __MSW32__
extern DWORD event_id; //event thread id
#endif
void start_sbdaemon(); /*start the daemon */
void cleanup_sbdaemon(); /*forget about the daemon */
BOOL8 remote_display( //check for remote
char *name //name of host
);
DLLSYM void *getshm( /*get memory */
INT32 size /*required size */
);
void kick_daemon( /*empty queue */
INT8 mode /*control mode */
);
#ifdef __MSW32__
int two_way_pipe ( //do one file
const char *file, //program to run
const char *argv[], //args to execvp
HANDLE fds[] //output fds
);
#endif
#endif

View File

@ -1,135 +0,0 @@
/**********************************************************************
* File: sbgconst.h (Formerly sbconst.h)
* Description: Header file of constants needed by graphics code.
* Author: Ray Smith
* Created: Thu May 24 14:19:43 BST 1990
*
* (C) Copyright 1990, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#ifndef SBGCONST_H
#define SBGCONST_H
//This file contains all the symbols and constants that the user sees
//that are not defined by Starbase.
#include "host.h"
#define WINDOWNAMESIZE 13 /*max size of name */
#define MAXWINDOWS 64 /*max allowed windows */
#define MAXWINDOWNAME 1024 /*max name length */
#define NO_WINDOW 0 /*no legal window */
#define SMDWINDOW 0 /*use smd, no window */
#define SCROLLINGWIN 1 /*scrolling window */
#define FULLSIZEWIN 2 /*non-scrolling window */
#define DCWIN 3 /*dc drawing only */
#define M_DOT 0 /*marker_types */
#define M_PLUS 1 /*starbase markers */
#define M_ASTERISK 2
#define M_CIRCLE 3
#define M_CROSS 4
#define M_TRIANGLE 5
#define M_SQUARE 6
#define M_DIAMOND 7
#define M_CROSSED_SQUARE 8
class WINFD;
typedef WINFD *WINDOW; //compatible with old code
typedef enum {
BLACK,
WHITE,
RED,
YELLOW,
GREEN,
CYAN,
BLUE,
MAGENTA,
AQUAMARINE,
DARK_SLATE_BLUE,
LIGHT_BLUE,
MEDIUM_BLUE,
MIDNIGHT_BLUE,
NAVY_BLUE,
SKY_BLUE,
SLATE_BLUE,
STEEL_BLUE,
CORAL,
BROWN,
SANDY_BROWN,
GOLD,
GOLDENROD,
DARK_GREEN,
DARK_OLIVE_GREEN,
FOREST_GREEN,
LIME_GREEN,
PALE_GREEN,
YELLOW_GREEN,
LIGHT_GREY,
DARK_SLATE_GREY,
DIM_GREY,
GREY,
KHAKI,
MAROON,
ORANGE,
ORCHID,
PINK,
PLUM,
INDIAN_RED,
ORANGE_RED,
VIOLET_RED,
SALMON,
TAN,
TURQUOISE,
DARK_TURQUOISE,
VIOLET,
WHEAT,
GREEN_YELLOW
} COLOUR; /*starbase colours */
enum ECHO_TYPE
{
NO_ECHO,
BEST_ECHO,
CROSS_HAIR_ECHO,
SMALL_X_ECHO,
RUBBER_LINE_ECHO,
RUBBER_BOX_ECHO,
ALPHA_ECHO
};
/*Event types*/
#define QUEUE_CLEAR 0 /*queue is empty */
#define DOWN_EVENT 1 /*button press */
#define MOVE_EVENT 2 /*pointer move */
#define UP_EVENT 3 /*button release */
#define KEYPRESS_EVENT 4 /*key pressed */
#define SELECT_EVENT 5 /*press-release pair */
#define ANY_EVENT 6 /*any type */
#define DESTROY_EVENT 7
typedef struct graphicsevent
{
struct graphicsevent *next; /*next event */
WINDOW fd; //structure of window
INT16 fildes; //unix only
INT8 type; /*event type */
char key; /*keypress */
float x, y; /*position of event */
float xmax, ymax; //for selection
} GRAPHICS_EVENT; /*event type */
typedef void (*EVENT_HANDLER) (GRAPHICS_EVENT *);
#endif

View File

@ -1,421 +0,0 @@
/* STARBASE_ID:sb.c.h 286.1 07/06/89 22:09:56 */
/* (c) Copyright Hewlett-Packard Company, 1985.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
All rights are reserved. Copying or other
reproduction of this program except for archival
purposes is prohibited without the prior
written consent of Hewlett-Packard Company.
RESTRICTED RIGHTS LEGEND
Use, duplication, or disclosure by the U.S. Government
is subject to restrictions as set forth in
subdivision (b) (3) (ii) of the Rights in Technical
Data and Computer Software clause at
52.227-7013.
HEWLETT-PACKARD COMPANY
Fort Collins, Colorado */
/************************************************************************
*
* definitions and types to be included with STARBASE application
* programs
*
***********************************************************************/
#ifndef _STARBASE_INCLUDED /* allow multiple inclusions */
#define _STARBASE_INCLUDED
/* kinds of graphics devices */
#define OUTDEV 0
#define INDEV 1
#define OUTINDEV 2
#define OUTMETA 3
#define INMETA 4
/* clear control parameters */
#define CLEAR_VDC_EXTENT 1
#define CLEAR_VIEWPORT 17
#define CLEAR_CLIP_RECTANGLE 33
#define CLEAR_DISPLAY_SURFACE 65
#define CLEAR_ALL_BANKS 128
#define CLEAR_ZBUFFER 256
/* clip control parameters */
#define CLIP_TO_RECT 1
#define CLIP_TO_VDC 2
#define CLIP_OFF 3
#define CLIP_TO_VIEWPORT 4
/* gopen open_mode parameter masks */
#define SPOOLED 0x01 /* if this bit is on, output is spooled */
//#define INIT 0x02 /* if this bit is on, device initialization occurs */
#define THREE_D 0x04 /* if this bit is on, all transformations are 3D */
#define RESET_DEVICE 0x08 /* if this bit is on, hard reset including p1 & p2 */
#define MODEL_XFORM 0x10 /* if this bit is on, matrix stack in modeling mode */
#define INT_XFORM 0x20 /* if this bit is on, matrix stack in modeling mode */
#define FLOAT_XFORM 0x40 /* if this bit is on, matrix stack in modeling mode */
/* color map modes set with shade_mode */
#define CMAP_NORMAL 0
#define CMAP_MONOTONIC 1
#define CMAP_FULL 4
/* double_buffer mode used to draw into the same buffer that is displayed */
#define DFRONT 4
/* double_buffer mode used to not clear buffer when switched */
#define SUPPRESS_CLEAR 8
/* light source types set with light_source */
#define DIRECTIONAL 0
#define POSITIONAL 1
#define ATTEN_LIGHT 2
#define SPOT_LIGHT 4
#define CONE_LIGHT 8
/* vertex orders set with vertex_format */
#define CLOCKWISE 0x0000
#define COUNTER_CLOCKWISE 0x0001
#define UNIT_NORMALS 0x0200
/* set p1 p2 units */
#define FRACTIONAL 0
#define METRIC 1
/* mapping modes */
#define ISOTROPIC 0
#define DISTORT 1
/* Starbase linetypes */
#define SOLID 0
#define DASH 1
#define DOT 2
#define DASH_DOT 3
#define DASH_DOT_DOT 4
#define LONG_DASH 5
#define CENTER_DASH 6
#define CENTER_DASH_DASH 7
/* wide endpoint types */
#define SQUARE 0
#define ROUNDED 1
/* depth cue models */
#define DC_MIN 2
#define DC_COLOR 4
/* distance modes for line_width, hatch_spacing */
#define VDC_UNITS 0
#define WC_UNITS 1
#define MC_UNITS WC_UNITS
#define DC_UNITS 2
/* polygon interior styles */
#define INT_HOLLOW 0
#define INT_SOLID 1
#define INT_PATTERN 2
#define INT_HATCH 3
#define INT_OUTLINE 4
#define INT_POINT 5
/* Matrix concatenation types */
#define PRE 0
#define POST 1
#define REPLACE 0
#define PUSH 1
/* Viewing matrix change types */
#define REPLACE_VW 0
#define PRE_CONCAT_VW 1
#define POST_CONCAT_VW 2
/* character switching modes */
#define ISO_7BIT 0
#define ISO_8BIT 1
#define HP_8BIT 2
/* text precision types */
#define STRING_TEXT 0
#define CHARACTER_TEXT 1
#define STROKE_TEXT 2
/* text transformation types */
#define VDC_TEXT 0
#define WORLD_COORDINATE_TEXT 1
#define TOS_TEXT 2
#define ANNOTATION_TEXT 3
/* text alignment enumerated types */
#define TA_LEFT 0
#define SB_TA_CENTER 1
#define TA_RIGHT 2
#define TA_CONTINUOUS_HORIZONTAL 3
#define TA_NORMAL_HORIZONTAL 4
#define TA_TOP 0
#define TA_CAP 1
#define TA_HALF 2
#define TA_BASE 3
#define SB_TA_BOTTOM 4
#define TA_CONTINUOUS_VERTICAL 5
#define TA_NORMAL_VERTICAL 6
/* character path and line path enumerated types */
#define PATH_RIGHT 0
#define PATH_LEFT 1
#define PATH_UP 2
#define PATH_DOWN 3
/* input device class enumerated types */
#define ALL 0
#define LOCATOR 1
#define CHOICE 4
/* event queue states */
#define EMPTY_NO_OVERFLOW 0
#define EMPTY_OVERFLOW 1
#define NOT_EMPTY_NO_OVERFLOW 2
#define NOT_EMPTY_OVERFLOW 3
/* event message link enumerated types */
#define SIMULTANEOUS_EVENT_FOLLOWS 0
#define SINGLE_EVENT 1
/* gerr printing flags */
#define NO_ERROR_PRINTING 0
#define PRINT_ERRORS 1
#define PRINT_WARNINGS 2
/* arc close_types */
#define NO_CHORD 0
#define PIE 1
#define CHORD 2
/* spline orders and rationalities */
#define NONRATIONAL 0
//#define RATIONAL 1
#define LINEAR 2
#define QUADRATIC 3
#define CUBIC 4
#define QUARTIC 5
#define QUINTIC 6
#define DC_VALUES 0
#define VDC_VALUES 2
#define STEP_SIZE 3
/* transform_point modes */
#define MC_TO_WC 0
#define MC_TO_WORLD 0
#define MC_TO_VDC 1
#define WC_TO_VDC 2
#define WORLD_TO_VDC 2
#define WC_TO_MC 3
#define WORLD_TO_MC 3
#define VDC_TO_MC 4
#define VDC_TO_WC 5
#define VDC_TO_WORLD 5
#define INTVDC_TO_DC 6
#define DC_TO_INTVDC 7
/* view_camera projection types */
#define CAM_PERSPECTIVE 0.0
#define CAM_PARALLEL 1.0
/* plane printing modes */
#define ALL_PLANES -1
#define PIXEL_MAJOR -1
#define PLANE_MAJOR -2
/* hatch types */
#define PARALLEL_HATCH 0
#define CROSSHATCH 1
/* highlight attribute types */
#define HL_COLOR 1
#define HL_STYLE 2
/* Hardware cursor control types */
#define REQUEST_HW_CURSOR 1
#define REQUEST_SW_CURSOR 2
#define FORCE_HW_CURSOR 3
#define REQUEST_HW_ECHO 1
#define REQUEST_SW_ECHO 2
#define FORCE_HW_ECHO 3
/* cgm encoding types */
#define CGM_BINARY 1
#define CGM_CHARACTER 2
#define CGM_CLEAR_TEXT 3
/* GLOBAL gescapes */
#define SWITCH_SEMAPHORE 0
#define READ_COLOR_MAP 1
#define BLINK_PLANES 2
#define BLINK_INDEX 3
/* GLOBAL raster gescapes */
#define R_GET_FRAME_BUFFER 20
#define R_LOCK_DEVICE 21
#define R_UNLOCK_DEVICE 22
#define R_GET_WINDOW_INFO 23
#define R_FULL_FRAME_BUFFER 24
#define R_ALLOC_OFFSCREEN 25
#define R_FREE_OFFSCREEN 26
#define R_BIT_MODE 27
#define R_BIT_MASK 28
#define R_DEF_FILL_PAT 29
#define R_OVERLAY_ECHO 30
#define R_OV_ECHO_COLORS 31
#define R_DEF_ECHO_TRANS 32
#define R_TRANSPARENCY_INDEX 33
#define R_LINE_TYPE 34
#define R_ECHO_FG_BG_COLORS 35
#define R_DMA_MODE 36
#define R_ECHO_MASK 37
#define R_ECHO_CONTROL 38
#define R_OFFSCREEN_ALLOC 1106
#define R_OFFSCREEN_FREE 1107
/* HPGL gescapes */
#define HPGL_WRITE_BUFFER 100
#define HPGL_SET_PEN_NUM 101
#define HPGL_SET_PEN_SPEED 102
#define HPGL_SET_PEN_WIDTH 103
#define HPGL_READ_BUFFER 104
/* HPGL2 gescapes */
#define HPGL2_SET_MEDIA_TYPE 105
#define HPGL2_LOGICAL_PEN_WIDTH 106
#define HPGL2_CUTTER_CONTROL 107
#define HPGL2_REPLOT 108
#define HPGL2_FONT_TYPEFACE 109
#define HPGL2_ADAPTIVE_LINES 110
#define HPGL2_SET_QUALITY 111
#define HPGL2_SET_CMAP_SIZE 112
#define HPGL2_FONT_WEIGHT 113
#define HPGL2_FONT_POSTURE 114
/* HP26XX gescapes */
#define HP26_PRINT_ESC 200
#define HPTERM_PRINT_ESC 200
#define HPTERM_640x400 201
/* 98700 gescapes */
#define GB_NONE 300
/* 98710 gescapes */
#define GA_NONE 400
/* 300l gescapes */
#define TC_HALF_PIXEL 500
/* HIL and keyboard gescapes */
#define ENABLE_AUTO_PROMPT 600
#define DISABLE_AUTO_PROMPT 601
#define PROMPT_ON 602
#define PROMPT_OFF 603
#define TRIGGER_ON_RELEASE 604
#define IGNORE_RELEASE 605
#define REPORT_PROXIMITY 606
#define IGNORE_PROXIMITY 607
#define ENABLE_ACKNOWLEDGE 608
#define DISABLE_ACKNOWLEDGE 609
#define SET_ACCELERATION 610 /* hil acceleration multiplier */
/* GKSM gescapes */
#define GKSM_WRITE_ITEM 700
#define GKSM_GET_ITEM_TYPE 701
#define GKSM_READ_ITEM 702
#define GKSM_SKIP_ITEM 703
#define GKSM_INQ_COLOR_NDCES 704
#define GKSM_INQ_PAT_REP 705
/* 98721 gescapes */
#define TRANSPARENCY 800
#define ZBUFFER_ALLOC 801
#define LS_OVERFLOW_CONTROL 802
#define PATTERN_FILL 803
#define ZWRITE_ENABLE 804
#define ZSTATE_SAVE 805
#define ZSTATE_RESTORE 806
/* SMDpixel and SMDpixel3 gescapes */
#define SMD_SUPPLY_MEM_BUFF 900
#define SMD_GET_MEM_REQUIRED 901
#define SMD_DEFINE_XY 902
#define SMD_DEFINE_DEPTH 903
#define SMD_ALLOCATE_MEMORY 904
/* Xn gescapes */
#define XN_INPUT_RAW 1000
/* raw mode (TRUE) returns LK201 keycodes
cooked mode (FALSE) returns ASCII */
#define XN_KEY_RELEASE 1001 /* turn on/off key release events */
#define XN_BUTTON_RELEASE 1002 /* turn on/off button release events */
/* 98549/49/50/56 gescapes */
#define GR2D_MASK_ENABLE 1100
#define GR2D_MASK_RULE 1101
#define GR2D_DEF_MASK 1102
#define GR2D_FILL_PATTERN 1103
#define GR2D_OVERLAY_TRANSPARENT 1104
#define GR2D_REPLICATE 1105
#define GR2D_ALLOC_OFFSCREEN 1106
#define GR2D_FREE_OFFSCREEN 1107
#define GR2D_PLANE_MASK 1108
#define GR2D_INQ_CLIST_ADDR 1109
#define GR2D_LOAD_CLIST 1110
#define GR2D_CONVEX_POLYGONS 1112
/* hp98730/31 driver gescapes */
#define PAN_AND_ZOOM 1200
#define OVERLAY_BLEND 1201
#define IMAGE_BLEND 1202
#define SET_BANK_CMAP 1203
#define GAMMA_CORRECTION 1204
#define INQ_GAMMA_CORRECTION 1205
#define FULL_COLOR_INDEX 1206
#define POLYGON_TRANSPARENCY 1207
#define CLIP_OVERFLOW 1208
/* hp98704/05 gescapes */
#define SET_REPLACEMENT_RULE 1250
/* hpcgm driver gescapes */
#define CGMESC_ENCODING 1300
#define CGMESC_ESCAPE_ELT 1301
#define CGMESC_MET_NAME 1302
#define CGMESC_PIC_NAME 1303
#define CGMESC_FONT_IX 1304
#define CGMESC_MESSAGE 1305
#define CGMESC_APPL_DATA 1306
#define CGMESC_VDC_PREC 1307
#define CGMESC_TOP_MODE 1308
typedef union
{
int i[64];
float f[64];
char c[255];
} gescape_arg;
typedef struct
{
float refx, refy, refz;
float camx, camy, camz;
float upx, upy, upz;
float field_of_view;
float front, back;
float projection;
} camera_arg;
#endif /* _STARBASE_INCLUDED */

View File

@ -1,248 +0,0 @@
/**********************************************************************
* File: sbgtypes.h (Formerly sbtypes.h)
* Description: Structures for the Starbase/X daemon interface.
* Author: Ray Smith
* Created: Wed May 16 09:26:35 BST 1990
*
* (C) Copyright 1990, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#ifndef SBGTYPES_H
#define SBGTYPES_H
//This file contains all the symbols and types that are not of concern
//to the user, but are common to both the client and the sbdaemon side.
#include "sbgconst.h"
#ifdef __UNIX__
#include <sys/types.h>
#endif
#define CHECK_TIME 1000 /*1 millisecond */
#define AWAIT_TIME 999999 /*1 second */
#define INFD 0 /*index to fds */
#define OUTFD 1 /*for read/write */
#define EVENTSIZE 16 //event buffer
#define PRIMITIVES (*(INT32*)((char*)shminfo.shmstart+shminfo.shmsize))
#define EVENT_TAIL (*(INT32*)((char*)shminfo.shmstart+shminfo.shmsize+sizeof(INT32)))
#define EVENT_HEAD (*(INT32*)((char*)shminfo.shmstart+shminfo.shmsize+2*sizeof(INT32)))
#define EVENT_INDEX(index) (((SBD_GRAPHICS_EVENT*)((char*)shminfo.shmstart+shminfo.shmsize+3*sizeof(INT32)))[index])
typedef enum {
LINECOLOUR, /*line_color_index */
PERIMETERCOLOUR, /*perimeter_color_index */
FILLCOLOUR, /*fill_color_index */
MARKERCOLOUR, /*marker_color_index */
TEXTCOLOUR, /*text_color_index */
TEXTFONT, /*text_font_index */
CHARHEIGHT, /*character_height */
LINETYPE, /*line_type */
MARKERTYPE, /*marker_type */
MARKERSIZE, /*marker_size */
MARKERMODE, /*mode in markersize */
INTERIORSTYLE, /*interior_style */
EDGESTYLE, /*edge in interior_style */
MOVE2D, /*move2d */
DRAW2D, /*draw2d */
RECTANGLE, /*rectangle */
TEXT_ALIGNMENT, //alginment
POLYLINE2D, /*polyline2d */
POLYGON2D, /*polygon2d */
POLYMARKER2D, /*polymarker2d */
TEXT2D, /*text2d */
APPENDTEXT, /*append_text */
ELLIPSE, /*ellipse */
ARC, /*arc */
SHOWIMAGE, /*display image */
SHOWLINE, /*send image line */
CREATE, /*create_window */
DESTROY, /*destroy_window */
CLEAR, /*clear_view_surface */
VDCEXTENT, /*vdc_extent */
MAKECURRENT, /*make_picture_current */
SETSIGNALS, //add callback
SETECHO, //change cursor
SYNCWIN, //sychronize
RE_COMP_COLMAP //Re-compute colourmap
} CALL_TYPE; /*type of call */
typedef union
{
INT16 fd; /*input fd */
void *next; /*turns to link */
} HEADUNION; /*header of structure */
typedef union
{
float f; /*parameter union */
INT32 i; /*to reduce structures */
} PARAMUNION;
typedef struct
{
PARAMUNION p; /*single parameter */
} ONEPARAM;
typedef struct
{
PARAMUNION p[2]; /*two params */
} TWOPARAMS;
typedef struct
{
PARAMUNION p[4]; /*4 params */
} FOURPARAMS;
typedef struct
{
PARAMUNION p[8]; /*8 params */
} EIGHTPARAMS;
typedef struct
{
HEADUNION header; /*fd/next op */
CALL_TYPE type; /*call type */
ONEPARAM param; /*single parameter */
} ONEOP;
typedef struct
{
HEADUNION header; /*fd/next op */
CALL_TYPE type; /*call type */
TWOPARAMS param; /*single parameter */
} TWOOP;
typedef struct
{
HEADUNION header; /*fd/next op */
CALL_TYPE type; /*call type */
FOURPARAMS param; /*single parameter */
} FOUROP;
typedef struct
{
HEADUNION header; /*fd/next op */
CALL_TYPE type; /*call type */
EIGHTPARAMS param; /*single parameter */
} EIGHTOP;
typedef struct
{
float *clist; /*coord list */
INT32 numpts; /*number of coords */
INT32 flags; /*move/draws on/off */
} POLYPARAM; /*polygon params */
typedef struct
{
HEADUNION header; /*fd/next */
CALL_TYPE type; /*operator type */
POLYPARAM param; /*parameters */
float polyxmin, polyxmax; /*bounding box */
float polyymin, polyymax; /*of polyline */
float clist[1]; /*place holder */
} POLYOP; /*poly line/marker */
typedef struct
{
float x, y; /*coords of text */
char *string; /*string to draw */
INT32 xform; /*coord transform */
INT32 more; /*any more text */
} TEXTPARAM; /*text parameters */
typedef struct
{
char *string; /*string to draw */
INT32 xform; /*coord transform */
INT32 more; /*any more text */
} APPENDPARAM; /*text parameters */
typedef struct
{
HEADUNION header; /*fd/next */
CALL_TYPE type; /*operator type */
TEXTPARAM param; /*parameters */
char chars[4]; /*place holder */
} TEXTOP; /*poly line/marker */
typedef struct
{
HEADUNION header; /*fd/next */
CALL_TYPE type; /*operator type */
APPENDPARAM param; /*parameters */
char chars[4]; /*place holder */
} APPENDOP; /*poly line/marker */
typedef struct
{
HEADUNION header; /*fd/next */
CALL_TYPE type; /*operator type */
INT32 size; /*size of structure */
UINT8 line[2]; /*image line */
} IMAGEOP; /*image passing */
typedef struct
{
HEADUNION header; /*fd/next */
CALL_TYPE type; /*operator type */
INT16 xpos, ypos; /*initial position */
INT16 xsize, ysize; /*initial size */
float xmin, xmax; /*scrolling limits */
float ymin, ymax;
BOOL8 downon; /*events required */
BOOL8 moveon;
BOOL8 upon;
BOOL8 keyon;
INT32 window_type; /*false for SMD */
char name[MAXWINDOWNAME]; /*name of window */
} CREATEOP;
typedef struct
{
#ifdef __UNIX__
int fds[2]; /*I/O files */
int shmid; /*shared memory id */
#else
#ifdef __PCDEMON__
int fds[2]; /*I/O files */
#else
HANDLE fds[2]; /*I/O files */
#endif
HANDLE shmid; //handle to it
#endif
void *shmstart; /*addr of shm seg */
INT32 usedsize; /*amount used */
INT32 shmsize; /*size of shm seg */
#ifdef __UNIX
pid_t pid; /*child process id */
#endif
} SHMINFO; /*shared memory info */
typedef struct sbdgraphicsevent
{
struct sbdgraphicsevent *next; /*next event */
INT16 fd; //unix only
INT8 type; /*event type */
char key; /*keypress */
float x, y; /*position of event */
} SBD_GRAPHICS_EVENT; /*event type */
//typedef void (*SBFUNC)(WINFD*,...); /*starbase function*/
typedef void (*DELFUNC) (void *, INT32);
/*deletion function */
typedef INT16 SBDWINDOW;
#endif

751
viewer/scrollview.cpp Normal file
View File

@ -0,0 +1,751 @@
///////////////////////////////////////////////////////////////////////
// File: scrollview.cc
// Description: ScrollView
// Author: Joern Wanke
// Created: Thu Nov 29 2007
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// This class contains the main ScrollView-logic,
// e.g. parsing & sending messages, images etc.
const bool kDebugMode = false;
const int kSvPort = 8461;
const int kMaxMsgSize = 4096;
#include "scrollview.h"
#include <stdarg.h>
#include <iostream>
#include <map>
#include <utility>
#include "svutil.h"
#ifdef HAVE_LIBLEPT
#include "allheaders.h"
#endif
// A map between the window IDs and their corresponding pointers.
static std::map<int, ScrollView*> svmap;
// A map of all semaphores waiting for a specific event on a specific window.
static std::map<std::pair<ScrollView*, SVEventType>,
std::pair<SVSemaphore*, SVEvent*> > waiting_for_events;
SVMutex* mutex_waiting;
SVEvent* SVEvent::copy() {
SVEvent* any = new SVEvent;
any->command_id = command_id;
any->counter = counter;
any->parameter = new char[strlen(parameter) + 1];
strncpy(any->parameter, parameter, strlen(parameter));
any->parameter[strlen(parameter)] = '\0';
any->type = type;
any->x = x;
any->y = y;
any->x_size = x_size;
any->y_size = y_size;
any->window = window;
return any;
}
// This is the main loop which handles the ScrollView-logic from the server
// to the client. It basically loops through messages, parses them to events
// and distributes it to the waiting handlers.
// It is run from a different thread and synchronizes via SVSync.
void* ScrollView::MessageReceiver(void* a) {
int counter_event_id = 0; //ongoing counter
char* message = NULL;
// Wait until a new message appears in the input stream_.
do {
message = ScrollView::GetStream()->Receive();
} while (message == NULL);
// This is the main loop which iterates until the server is dead (strlen = -1).
// It basically parses for 3 different messagetypes and then distributes the
// events accordingly.
while (strlen(message) != -1) {
// The new event we create.
SVEvent* cur = new SVEvent;
// The ID of the corresponding window.
int window_id;
int ev_type;
if (kDebugMode) { std::cout << "(s->C)" << message << "\n"; }
int n;
// Fill the new SVEvent properly.
sscanf(message, "%d,%d,%d,%d,%d,%d,%d,%n", &window_id, &ev_type, &cur->x,
&cur->y, &cur->x_size, &cur->y_size, &cur->command_id, &n);
char* p = (message + n);
cur->window = svmap[window_id];
if (cur->window != NULL) {
cur->parameter = new char[strlen(p) + 1];
strncpy(cur->parameter, p, strlen(p) + 1);
if (strlen(p) > 0) { // remove the last \n
cur->parameter[strlen(p)] = '\0';
}
cur->type = static_cast<SVEventType>(ev_type);
cur->y = cur->window->TranslateYCoordinate(cur->y);
cur->counter = counter_event_id;
// Increase by 2 since we will also create an SVET_ANY event from cur, which
// will have a counter_id of cur + 1 (and thus gets processed after cur).
counter_event_id += 2;
// In case of an SVET_EXIT event, quit the whole application.
if (ev_type == SVET_EXIT) { ScrollView::Exit(); }
// Place two copies of it in the table for the window.
cur->window->SetEvent(cur);
// Check if any of the threads currently waiting want it.
std::pair<ScrollView*, SVEventType> awaiting_list(cur->window,
cur->type);
std::pair<ScrollView*, SVEventType> awaiting_list_any(cur->window,
SVET_ANY);
std::pair<ScrollView*, SVEventType> awaiting_list_any_window(NULL,
SVET_ANY);
mutex_waiting->Lock();
if (waiting_for_events.count(awaiting_list) > 0) {
waiting_for_events[awaiting_list].second = cur;
waiting_for_events[awaiting_list].first->Signal();
} else if (waiting_for_events.count(awaiting_list_any) > 0) {
waiting_for_events[awaiting_list_any].second = cur;
waiting_for_events[awaiting_list_any].first->Signal();
} else if (waiting_for_events.count(awaiting_list_any_window) > 0) {
waiting_for_events[awaiting_list_any_window].second = cur;
waiting_for_events[awaiting_list_any_window].first->Signal();
} else {
// No one wanted it, so delete it.
delete cur;
}
mutex_waiting->Unlock();
// Signal the corresponding semaphore twice (for both copies).
ScrollView* sv = svmap[window_id];
sv->Signal();
sv->Signal();
}
// Wait until a new message appears in the input stream_.
do {
message = ScrollView::GetStream()->Receive();
} while (message == NULL);
}
return 0;
}
// Table to implement the color index values in the old system.
int table_colors[ScrollView::GREEN_YELLOW+1][4]= {
{0, 0, 0, 0}, // NONE (transparent)
{0, 0, 0, 255}, // BLACK.
{255, 255, 255, 255}, // WHITE.
{255, 0, 0, 255}, // RED.
{255, 255, 0, 255}, // YELLOW.
{0, 255, 0, 255}, // GREEN.
{0, 255, 255, 255}, // CYAN.
{0, 0, 255, 255}, // BLUE.
{255, 0, 255, 255}, // MAGENTA.
{0, 128, 255, 255}, // AQUAMARINE.
{0, 0, 64, 255}, // DARK_SLATE_BLUE.
{128, 128, 255, 255}, // LIGHT_BLUE.
{64, 64, 255, 255}, // MEDIUM_BLUE.
{0, 0, 32, 255}, // MIDNIGHT_BLUE.
{0, 0, 128, 255}, // NAVY_BLUE.
{192, 192, 255, 255}, // SKY_BLUE.
{64, 64, 128, 255}, // SLATE_BLUE.
{32, 32, 64, 255}, // STEEL_BLUE.
{255, 128, 128, 255}, // CORAL.
{128, 64, 0, 255}, // BROWN.
{128, 128, 0, 255}, // SANDY_BROWN.
{192, 192, 0, 255}, // GOLD.
{192, 192, 128, 255}, // GOLDENROD.
{0, 64, 0, 255}, // DARK_GREEN.
{32, 64, 0, 255}, // DARK_OLIVE_GREEN.
{64, 128, 0, 255}, // FOREST_GREEN.
{128, 255, 0, 255}, // LIME_GREEN.
{192, 255, 192, 255}, // PALE_GREEN.
{192, 255, 0, 255}, // YELLOW_GREEN.
{192, 192, 192, 255}, // LIGHT_GREY.
{64, 64, 128, 255}, // DARK_SLATE_GREY.
{64, 64, 64, 255}, // DIM_GREY.
{128, 128, 128, 255}, // GREY.
{64, 192, 0, 255}, // KHAKI.
{255, 0, 192, 255}, // MAROON.
{255, 128, 0, 255}, // ORANGE.
{255, 128, 64, 255}, // ORCHID.
{255, 192, 192, 255}, // PINK.
{128, 0, 128, 255}, // PLUM.
{255, 0, 64, 255}, // INDIAN_RED.
{255, 64, 0, 255}, // ORANGE_RED.
{255, 0, 192, 255}, // VIOLET_RED.
{255, 192, 128, 255}, // SALMON.
{128, 128, 0, 255}, // TAN.
{0, 255, 255, 255}, // TURQUOISE.
{0, 128, 128, 255}, // DARK_TURQUOISE.
{192, 0, 255, 255}, // VIOLET.
{128, 128, 0, 255}, // WHEAT.
{128, 255, 0, 255} // GREEN_YELLOW
};
/*******************************************************************************
* Scrollview implementation.
*******************************************************************************/
SVNetwork* ScrollView::stream_ = NULL;
int ScrollView::nr_created_windows_ = 0;
// Calls Initialize with all arguments given.
ScrollView::ScrollView(const char* name, int x_pos, int y_pos, int x_size,
int y_size, int x_canvas_size, int y_canvas_size,
bool y_axis_reversed, const char* server_name) {
Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
y_axis_reversed, server_name);}
// Calls Initialize with default argument for server_name_.
ScrollView::ScrollView(const char* name, int x_pos, int y_pos, int x_size,
int y_size, int x_canvas_size, int y_canvas_size,
bool y_axis_reversed) {
Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
y_axis_reversed, "localhost");
}
// Calls Initialize with default argument for server_name_ & y_axis_reversed.
ScrollView::ScrollView(const char* name, int x_pos, int y_pos, int x_size,
int y_size, int x_canvas_size, int y_canvas_size) {
Initialize(name, x_pos, y_pos, x_size, y_size, x_canvas_size, y_canvas_size,
false, "localhost");
}
// Sets up a ScrollView window, depending on the constructor variables.
void ScrollView::Initialize(const char* name, int x_pos, int y_pos, int x_size,
int y_size, int x_canvas_size, int y_canvas_size,
bool y_axis_reversed, const char* server_name) {
// If this is the first ScrollView Window which gets created, there is no
// network connection yet and we have to set it up in a different thread.
if (stream_ == NULL) {
nr_created_windows_ = 0;
stream_ = new SVNetwork(server_name, kSvPort);
mutex_waiting = new SVMutex();
if (kDebugMode) {
std::cout << "(C->s) svmain = "
<< "luajava.bindClass('com.google.scrollview.ScrollView')\n";
}
SendRawMessage(
"svmain = luajava.bindClass('com.google.scrollview.ScrollView')\n");
SVSync::StartThread(MessageReceiver, NULL);
}
// Set up the variables on the clientside.
nr_created_windows_++;
event_handler_ = NULL;
y_axis_is_reversed_ = y_axis_reversed;
y_size_ = y_canvas_size;
window_name_ = name;
window_id_ = nr_created_windows_;
svmap[window_id_] = this;
for (int i = 0; i < SVET_COUNT; i++) {
event_table_[i] = NULL;
}
mutex_ = new SVMutex();
semaphore_ = new SVSemaphore();
// Set up an actual Window on the client side.
char message[kMaxMsgSize];
snprintf(message, sizeof(message),
"w%u = luajava.newInstance('com.google.scrollview.ui"
".SVWindow','%s',%u,%u,%u,%u,%u,%u,%u)\n",
window_id_, window_name_,
window_id_, x_pos,
TranslateYCoordinate(y_pos), x_size,
y_size_, x_canvas_size, y_canvas_size);
if (kDebugMode) {
std::cout << "(C->s)" << message;
}
SendRawMessage(message);
SVSync::StartThread(StartEventHandler, this);
}
// Sits and waits for events on this window.
void* ScrollView::StartEventHandler(void* a) {
ScrollView* sv = (ScrollView*) a;
SVEvent* new_event;
do {
stream_->Flush();
sv->semaphore_->Wait();
new_event = NULL;
int serial = INT_MAX;
int k = -1;
sv->mutex_->Lock();
// Check every table entry if he is is valid and not already processed.
for (int i = 0; i < SVET_COUNT; i++) {
if ((sv->event_table_[i] != NULL) &&
(sv->event_table_[i]->counter < serial)) {
new_event = sv->event_table_[i];
serial = sv->event_table_[i]->counter;
k = i;
}
}
// If we didnt find anything we had an old alarm and just sleep again.
if (new_event != NULL) {
sv->event_table_[k] = NULL;
sv->mutex_->Unlock();
if (sv->event_handler_ != NULL) { sv->event_handler_->Notify(new_event); }
if (new_event->type == SVET_DESTROY) { sv = NULL; }
delete new_event; // Delete the pointer after it has been processed.
} else { sv->mutex_->Unlock(); }
// The thread should run as long as its associated window is alive.
} while (sv != NULL);
return 0;
}
ScrollView::~ScrollView() {
// So the event handling thread can quit.
SendMsg("destroy()");
SVEvent* sve = AwaitEvent(SVET_DESTROY);
delete sve;
delete mutex_;
delete semaphore_;
svmap.erase(window_id_);
}
// Send a message to the server, attaching the window id.
void ScrollView::SendMsg(const char* format, ...) {
va_list args;
char message[kMaxMsgSize];
va_start(args, format); // variable list
vsnprintf(message, kMaxMsgSize, format, args);
va_end(args);
char form[kMaxMsgSize];
snprintf(form, kMaxMsgSize, "w%u:%s\n", window_id_, message);
if (kDebugMode) { std::cout << "(C->s)" << form; }
stream_->Send(form);
}
// Send a message to the server without a
// window id. Used for global events like exit().
void ScrollView::SendRawMessage(const char* msg) {
stream_->Send(msg);
}
// Add an Event Listener to this ScrollView Window
void ScrollView::AddEventHandler(SVEventHandler* listener) {
event_handler_ = listener;
}
void ScrollView::Signal() {
semaphore_->Signal();
}
void ScrollView::SetEvent(SVEvent* svevent) {
// Copy event
SVEvent* any = svevent->copy();
SVEvent* specific = svevent->copy();
any->counter = specific->counter + 1;
// Place both events into the queue.
mutex_->Lock();
// Delete the old objects..
if (event_table_[specific->type] != NULL) {
delete event_table_[specific->type]; }
if (event_table_[SVET_ANY] != NULL) {
delete event_table_[SVET_ANY]; }
// ...and put the new ones in the table.
event_table_[specific->type] = specific;
event_table_[SVET_ANY] = any;
mutex_->Unlock();
}
// Block until an event of the given type is received.
// Note: The calling function is responsible for deleting the returned
// SVEvent afterwards!
SVEvent* ScrollView::AwaitEvent(SVEventType type) {
// Initialize the waiting semaphore.
SVSemaphore* sem = new SVSemaphore();
std::pair<ScrollView*, SVEventType> ea(this, type);
mutex_waiting->Lock();
waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, NULL);
mutex_waiting->Unlock();
// Wait on it, but first flush.
stream_->Flush();
sem->Wait();
// Process the event we got woken up for (its in waiting_for_events pair).
mutex_waiting->Lock();
SVEvent* ret = waiting_for_events[ea].second;
waiting_for_events.erase(ea);
mutex_waiting->Unlock();
return ret;
}
// Block until any event on any window is received.
// No event is returned here!
SVEvent* ScrollView::AwaitEventAnyWindow() {
// Initialize the waiting semaphore.
SVSemaphore* sem = new SVSemaphore();
std::pair<ScrollView*, SVEventType> ea(NULL, SVET_ANY);
mutex_waiting->Lock();
waiting_for_events[ea] = std::pair<SVSemaphore*, SVEvent*> (sem, NULL);
mutex_waiting->Unlock();
// Wait on it.
stream_->Flush();
sem->Wait();
// Process the event we got woken up for (its in waiting_for_events pair).
mutex_waiting->Lock();
SVEvent* ret = waiting_for_events[ea].second;
waiting_for_events.erase(ea);
mutex_waiting->Unlock();
return ret;
}
/*******************************************************************************
* LUA "API" functions.
*******************************************************************************/
// Sets the position from which to draw to (x,y).
void ScrollView::SetCursor(int x, int y) {
current_position_x_ = x;
current_position_y_ = y;
}
// Draws from the current position to (x,y) and sets the new position to it.
void ScrollView::DrawTo(int x, int y) {
Line(current_position_x_, current_position_y_, x, y);
SetCursor(x, y);
}
// Set the visibility of the window.
void ScrollView::SetVisible(bool visible) {
if (visible) { SendMsg("setVisible(true)");
} else { SendMsg("setVisible(false)"); }
}
// Set the alwaysOnTop flag.
void ScrollView::AlwaysOnTop(bool b) {
if (b) { SendMsg("setAlwaysOnTop(true)");
} else { SendMsg("setAlwaysOnTop(false)"); }
}
// Adds a message entry to the message box.
void ScrollView::AddMessage(const char* format, ...) {
va_list args;
char message[kMaxMsgSize];
char form[kMaxMsgSize];
va_start(args, format); // variable list
vsnprintf(message, kMaxMsgSize, format, args);
va_end(args);
snprintf(form, kMaxMsgSize, "w%u:%s", window_id_, message);
char* esc = AddEscapeChars(form);
SendMsg("addMessage(\"%s\")", esc);
delete[] esc;
}
// Set a messagebox.
void ScrollView::AddMessageBox() {
SendMsg("addMessageBox()");
}
// Exit the client completely (and notify the server of it).
void ScrollView::Exit() {
SendRawMessage("svmain:exit()");
exit(0);
}
// Clear the canvas.
void ScrollView::Clear() {
SendMsg("clear()");
}
// Draw a line using the current pen color.
void ScrollView::Line(int x1, int y1, int x2, int y2) {
SendMsg("drawLine(%d,%d,%d,%d)",
x1, TranslateYCoordinate(y1), x2, TranslateYCoordinate(y2));
}
// Set the stroke width.
void ScrollView::Stroke(float width) {
SendMsg("setStrokeWidth(%f)", width);
}
// Draw a rectangle using the current pen color.
// The rectangle is filled with the current brush color.
void ScrollView::Rectangle(int x1, int y1, int x2, int y2) {
SendMsg("drawRectangle(%d,%d,%d,%d)",
x1, TranslateYCoordinate(y1), x2, TranslateYCoordinate(y2));
}
// Draw an ellipse using the current pen color.
// The ellipse is filled with the current brush color.
void ScrollView::Ellipse(int x1, int y1, int width, int height) {
SendMsg("drawEllipse(%d,%d,%u,%u)",
x1, TranslateYCoordinate(y1), width, height);
}
// Set the pen color to the given RGB values.
void ScrollView::Pen(int red, int green, int blue) {
SendMsg("pen(%d,%d,%d)", red, green, blue);
}
// Set the pen color to the given RGB values.
void ScrollView::Pen(int red, int green, int blue, int alpha) {
SendMsg("pen(%d,%d,%d,%d)", red, green, blue, alpha);
}
// Set the brush color to the given RGB values.
void ScrollView::Brush(int red, int green, int blue) {
SendMsg("brush(%d,%d,%d)", red, green, blue);
}
// Set the brush color to the given RGB values.
void ScrollView::Brush(int red, int green, int blue, int alpha) {
SendMsg("brush(%d,%d,%d,%d)", red, green, blue, alpha);
}
// Set the attributes for future Text(..) calls.
void ScrollView::TextAttributes(const char* font, int pixel_size,
bool bold, bool italic, bool underlined) {
const char* b;
const char* i;
const char* u;
if (bold) { b = "true";
} else { b = "false"; }
if (italic) { i = "true";
} else { i = "false"; }
if (underlined) { u = "true";
} else { u = "false"; }
SendMsg("textAttributes('%s',%u,%s,%s,%s)", font, pixel_size,
b, i, u);
}
// Draw text at the given coordinates.
void ScrollView::Text(int x, int y, const char* mystring) {
SendMsg("drawText(%d,%d,'%s')", x, TranslateYCoordinate(y), mystring);
}
// Open and draw an image given a name at (x,y).
void ScrollView::Image(const char* image, int x_pos, int y_pos) {
SendMsg("openImage('%s')", image);
SendMsg("drawImage('%s',%d,%d)",
image, x_pos, TranslateYCoordinate(y_pos));
}
// Add new checkboxmenuentry to menubar.
void ScrollView::MenuItem(const char* parent, const char* name,
int cmdEvent, bool flag) {
if (parent == NULL) { parent = ""; }
if (flag) { SendMsg("addMenuBarItem('%s','%s',%d,true)",
parent, name, cmdEvent);
} else { SendMsg("addMenuBarItem('%s','%s',%d,false)",
parent, name, cmdEvent); }
}
// Add new menuentry to menubar.
void ScrollView::MenuItem(const char* parent, const char* name, int cmdEvent) {
if (parent == NULL) { parent = ""; }
SendMsg("addMenuBarItem('%s','%s',%d)", parent, name, cmdEvent);
}
// Add new submenu to menubar.
void ScrollView::MenuItem(const char* parent, const char* name) {
if (parent == NULL) { parent = ""; }
SendMsg("addMenuBarItem('%s','%s')", parent, name);
}
// Add new submenu to popupmenu.
void ScrollView::PopupItem(const char* parent, const char* name) {
if (parent == NULL) { parent = ""; }
SendMsg("addPopupMenuItem('%s','%s')", parent, name);
}
// Add new submenuentry to popupmenu.
void ScrollView::PopupItem(const char* parent, const char* name,
int cmdEvent, const char* value, const char* desc) {
if (parent == NULL) { parent = ""; }
char* esc = AddEscapeChars(value);
char* esc2 = AddEscapeChars(desc);
SendMsg("addPopupMenuItem('%s','%s',%d,'%s','%s')", parent, name,
cmdEvent, esc, esc2);
delete[] esc;
delete[] esc2;
}
// Send an update message for a single window.
void ScrollView::UpdateWindow() {
SendMsg("update()");
}
// Note: this is an update to all windows
void ScrollView::Update() {
for (std::map<int, ScrollView*>::iterator iter = svmap.begin();
iter != svmap.end(); ++iter) {
iter->second->UpdateWindow();
}
}
// Set the pen color, using an enum value (e.g. ScrollView::ORANGE)
void ScrollView::Pen(Color color) {
Pen(table_colors[color][0], table_colors[color][1],
table_colors[color][2], table_colors[color][3]);
}
// Set the brush color, using an enum value (e.g. ScrollView::ORANGE)
void ScrollView::Brush(Color color) {
Brush(table_colors[color][0],
table_colors[color][1],
table_colors[color][2],
table_colors[color][3]);
}
// Shows a modal Input Dialog which can return any kind of String
char* ScrollView::ShowInputDialog(const char* msg) {
SendMsg("showInputDialog(\"%s\")", msg);
SVEvent* ev;
// wait till an input event (all others are thrown away)
ev = AwaitEvent(SVET_INPUT);
char* p = new char[strlen(ev->parameter) + 1];
strncpy(p, ev->parameter, strlen(ev->parameter));
p[strlen(ev->parameter)] = '\0';
delete ev;
return p;
}
// Shows a modal Yes/No Dialog which will return 'y' or 'n'
int ScrollView::ShowYesNoDialog(const char* msg) {
SendMsg("showYesNoDialog(\"%s\")", msg);
SVEvent* ev;
// Wait till an input event (all others are thrown away)
ev = AwaitEvent(SVET_INPUT);
int a = ev->parameter[0];
delete ev;
return a;
}
#ifdef HAVE_LIBLEPT
// Send an image of type PIX.
void ScrollView::Image(PIX* image, int x_pos, int y_pos) {
int width = image->w;
int height = image->h;
l_uint32 bpp = image->d;
// PIX* do not have a unique identifier/name associated, so name them "lept".
SendMsg("createImage('%u',%u,%u,%u)", "lept", width, height, bpp);
if (bpp == 32) {
Transfer32bppImage(image);
} else if (bpp == 8) {
TransferGrayImage(image);
} else if (bpp == 1) {
TransferBinaryImage(image);
}
// PIX* do not have a unique identifier/name associated, so name them "lept".
SendMsg("drawImage('%u',%d,%d)", "lept", x_pos, y_pos);
}
// Sends each pixel as hex value like html, e.g. #00FF00 for green.
void ScrollView::Transfer32bppImage(PIX* image) {
int ppL = pixGetWidth(image);
int h = pixGetHeight(image);
int wpl = pixGetWpl(image);
int transfer_size= ppL * 7 + 1;
char* pixel_data = new char[transfer_size];
for (int y = 0; y < h; ++y) {
l_uint32* data = pixGetData(image) + y*wpl;
for (int x = 0; x < ppL; ++x, ++data) {
snprintf(&pixel_data[x*7], 7, "#%.2x%.2x%.2x",
GET_DATA_BYTE(data, COLOR_RED),
GET_DATA_BYTE(data, COLOR_GREEN),
GET_DATA_BYTE(data, COLOR_BLUE));
}
pixel_data[transfer_size - 1] = '\0';
SendRawMessage(pixel_data);
}
delete[] pixel_data;
}
// TODO add RunLengthEncoding to this or something similar
// TODO testme
// Sends for each pixel either '1' or '0'.
void ScrollView::TransferGrayImage(PIX* image) {
char pixel_data[image->w * 2 + 1];
for (int y = 0; y < image->h; y++) {
l_uint32* data = pixGetData(image) + y * pixGetWpl(image);
for (int x = 0; x < image->w; x++) {
snprintf(&pixel_data[x*2], 2, "%.2x", (GET_DATA_BYTE(data, x)));
pixel_data[image->w * 2] = '\0';
SendRawMessage(pixel_data);
}
}
}
// TODO add RunLengthEncoding to this or something similar
// Sends for each pixel either '1' or '0'.
void ScrollView::TransferBinaryImage(PIX* image) {
char pixel_data[image->w + 1];
for (int y = 0; y < image->h; y++) {
l_uint32* data = pixGetData(image) + y * pixGetWpl(image);
for (int x = 0; x < image->w; x++) {
if (GET_DATA_BIT(data, x))
{ pixel_data[x] = '1'; }
else
{ pixel_data[x] = '0'; }
}
pixel_data[image->w] = '\0';
SendRawMessage(pixel_data);
}
}
#endif
// Escapes the ' character with a \, so it can be processed by LUA.
// Note: The caller will have to make sure he deletes the newly allocated item.
char* ScrollView::AddEscapeChars(const char* input) {
const char* nextptr = strchr(input, '\'');
const char* lastptr = input;
char* message = new char[kMaxMsgSize];
int pos = 0;
while (nextptr != NULL) {
strncpy(message+pos, lastptr, nextptr-lastptr);
pos += nextptr - lastptr;
message[pos] = '\\';
pos += 1;
lastptr = nextptr;
nextptr = strchr(nextptr+1, '\'');
}
strncpy(message+pos, lastptr, strlen(lastptr));
message[pos+strlen(lastptr)] = '\0';
return message;
}
// Inverse the Y axis if the coordinates are actually inversed.
int ScrollView::TranslateYCoordinate(int y) {
if (!y_axis_is_reversed_) { return y;
} else { return y_size_ - y; }
}

401
viewer/scrollview.h Normal file
View File

@ -0,0 +1,401 @@
///////////////////////////////////////////////////////////////////////
// File: scrollview.h
// Description: ScrollView
// Author: Joern Wanke
// Created: Thu Nov 29 2007
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// ScrollView is designed as an UI which can be run remotely. This is the
// client code for it, the server part is written in java. The client consists
// mainly of 2 parts:
// The "core" ScrollView which sets up the remote connection,
// takes care of event handling etc.
// The other part of ScrollView consists of predefined API calls through LUA,
// which can basically be used to get a zoomable canvas in which it is possible
// to draw lines, text etc.
// Technically, thanks to LUA, its even possible to bypass the here defined LUA
// API calls at all and generate a java user interface from scratch (or
// basically generate any kind of java program, possibly even dangerous ones).
#ifndef THIRD_PARTY_TESSERACT_VIEWER_SCROLLVIEW_H__
#define THIRD_PARTY_TESSERACT_VIEWER_SCROLLVIEW_H__
#include <stdio.h>
class ScrollView;
class SVNetwork;
class SVMutex;
class SVSemaphore;
enum SVEventType {
SVET_DESTROY, // Window has been destroyed by user.
SVET_EXIT, // User has destroyed the last window by clicking on the 'X'.
SVET_CLICK, // Left button pressed.
SVET_SELECTION, // Left button selection.
SVET_INPUT, // There is some input (single key or a whole string).
SVET_MOUSE, // The mouse has moved with a button pressed.
SVET_MOTION, // The mouse has moved with no button pressed.
SVET_HOVER, // The mouse has stayed still for a second.
SVET_POPUP, // A command selected through a popup menu.
SVET_MENU, // A command selected through the menubar.
SVET_ANY, // Any of the above.
SVET_COUNT // Array sizing.
};
struct SVEvent {
~SVEvent() { delete [] parameter; }
SVEvent* copy();
SVEventType type; // What kind of event.
ScrollView* window; // Window event relates to.
int x; // Coords of click or selection.
int y;
int x_size; // Size of selection.
int y_size;
int command_id; // The ID of the possibly associated event (e.g. MENU)
char* parameter; // Any string that might have been passed as argument.
int counter; // Used to detect which kind of event to process next.
SVEvent() {
window = NULL;
parameter = NULL;
}
SVEvent(const SVEvent&);
SVEvent& operator=(const SVEvent&);
};
// The SVEventHandler class is used for Event handling: If you register your
// class as SVEventHandler to a ScrollView Window, the SVEventHandler will be
// called whenever an appropriate event occurs.
class SVEventHandler {
public:
// Gets called by the SV Window. Does nothing on default, overwrite this
// to implement the desired behaviour
virtual void Notify(const SVEvent* sve) { }
};
// The ScrollView class provides the expernal API to the scrollviewer process.
// The scrollviewer process manages windows and displays images, graphics and
// text while allowing the user to zoom and scroll the windows arbitrarily.
// Each ScrollView class instance represents one window, and stuff is drawn in
// the window through method calls on the class. The constructor is used to
// create the class instance (and the window).
class ScrollView {
public:
// Color enum for pens and brushes.
enum Color {
NONE,
BLACK,
WHITE,
RED,
YELLOW,
GREEN,
CYAN,
BLUE,
MAGENTA,
AQUAMARINE,
DARK_SLATE_BLUE,
LIGHT_BLUE,
MEDIUM_BLUE,
MIDNIGHT_BLUE,
NAVY_BLUE,
SKY_BLUE,
SLATE_BLUE,
STEEL_BLUE,
CORAL,
BROWN,
SANDY_BROWN,
GOLD,
GOLDENROD,
DARK_GREEN,
DARK_OLIVE_GREEN,
FOREST_GREEN,
LIME_GREEN,
PALE_GREEN,
YELLOW_GREEN,
LIGHT_GREY,
DARK_SLATE_GREY,
DIM_GREY,
GREY,
KHAKI,
MAROON,
ORANGE,
ORCHID,
PINK,
PLUM,
INDIAN_RED,
ORANGE_RED,
VIOLET_RED,
SALMON,
TAN,
TURQUOISE,
DARK_TURQUOISE,
VIOLET,
WHEAT,
GREEN_YELLOW // Make sure this one is last.
};
// Create a window. The pixel size of the window may be 0,0, in which case
// a default size is selected based on the size of your canvas.
// The canvas may not be 0,0 in size!
ScrollView(const char* name, int x_pos, int y_pos, int x_size, int y_size,
int x_canvas_size, int y_canvas_size);
// With a flag whether the x axis is reversed.
ScrollView(const char* name, int x_pos, int y_pos, int x_size, int y_size,
int x_canvas_size, int y_canvas_size, bool y_axis_reversed);
// Connect to a server other than localhost.
ScrollView(const char* name, int x_pos, int y_pos, int x_size, int y_size,
int x_canvas_size, int y_canvas_size, bool y_axis_reversed,
const char* server_name);
~ScrollView();
/*******************************************************************************
* Event handling
* To register as listener, the class has to derive from the SVEventHandler
* class, which consists of a notifyMe(SVEvent*) function that should be
* overwritten to process the event the way you want.
*******************************************************************************/
// Add an Event Listener to this ScrollView Window.
void AddEventHandler(SVEventHandler* listener);
// Block until an event of the given type is received.
SVEvent* AwaitEvent(SVEventType type);
// Block until any event on any window is received.
SVEvent* AwaitEventAnyWindow();
/*******************************************************************************
* Getters and Setters
*******************************************************************************/
// Returns the title of the window.
const char* GetName() { return window_name_; }
// Returns the unique ID of the window.
int GetId() { return window_id_; }
/*******************************************************************************
* API functions for LUA calls
* the implementations for these can be found in svapi.cc
* (keep in mind that the window is actually created through the ScrollView
* constructor, so this is not listed here)
*******************************************************************************/
#ifdef HAVE_LIBLEPT
// Draw a Pix on (x,y).
void Image(struct Pix* image, int x_pos, int y_pos);
#endif
// Flush buffers and update display.
static void Update();
// Exit the program.
static void Exit();
// Update the contents of a specific window.
void UpdateWindow();
// Erase all content from the window, but do not destroy it.
void Clear();
// Set pen color with an enum.
void Pen(Color color);
// Set pen color to RGB (0-255).
void Pen(int red, int green, int blue);
// Set pen color to RGBA (0-255).
void Pen(int red, int green, int blue, int alpha);
// Set brush color with an enum.
void Brush(Color color);
// Set brush color to RGB (0-255).
void Brush(int red, int green, int blue);
// Set brush color to RGBA (0-255).
void Brush(int red, int green, int blue, int alpha);
// Set attributes for future text, like font name (e.g.
// "Times New Roman"), font size etc..
// Note: The underlined flag is currently not supported
void TextAttributes(const char* font, int pixel_size,
bool bold, bool italic, bool underlined);
// Draw line from (x1,y1) to (x2,y2) with the current pencolor.
void Line(int x1, int y1, int x2, int y2);
// Set the stroke width of the pen.
void Stroke(float width);
// Draw a rectangle given upper left corner and lower right corner.
// The current pencolor is used as outline, the brushcolor to fill the shape.
void Rectangle(int x1, int y1, int x2, int y2);
// Draw an ellipse centered on (x,y).
// The current pencolor is used as outline, the brushcolor to fill the shape.
void Ellipse(int x, int y, int width, int height);
// Draw text with the current pencolor
void Text(int x, int y, const char* mystring);
// Draw an image from a local filename. This should be faster than createImage.
// WARNING: This only works on a local machine. This also only works image
// types supported by java (like bmp,jpeg,gif,png) since the image is opened by
// the server.
void Image(const char* image, int x_pos, int y_pos);
// Set the current position to draw from (x,y). In conjunction with...
void SetCursor(int x, int y);
// ...this function, which draws a line from the current to (x,y) and then
// sets the new position to the new (x,y), this can be used to easily draw
// polygons using vertices
void DrawTo(int x, int y);
// Set the SVWindow visible/invisible.
void SetVisible(bool visible);
// Set the SVWindow always on top or not always on top.
void AlwaysOnTop(bool b);
// Shows a modal dialog with "msg" as question and returns 'y' or 'n'.
int ShowYesNoDialog(const char* msg);
// Shows a modal dialog with "msg" as question and returns a char* string.
// Constraint: As return, only words (e.g. no whitespaces etc.) are allowed.
char* ShowInputDialog(const char* msg);
// Adds a messagebox to the SVWindow. This way, it can show the messages...
void AddMessageBox();
// ...which can be added by this command.
// This is intended as an "debug" output window.
void AddMessage(const char* format, ...);
// Custom messages (manipulating java code directly) can be send through this.
// Send a message to the server and attach the Id of the corresponding window.
// Note: This should only be called if you are know what you are doing, since
// you are fiddling with the Java objects on the server directly. Calling
// this just for fun will likely break your application!
// It is public so you can actually take use of the LUA functionalities, but
// be careful!
void SendMsg(const char* msg, ...);
// Custom messages (manipulating java code directly) can be send through this.
// Send a message to the server without adding the
// window id. Used for global events like Exit().
// Note: This should only be called if you are know what you are doing, since
// you are fiddling with the Java objects on the server directly. Calling
// this just for fun will likely break your application!
// It is public so you can actually take use of the LUA functionalities, but
// be careful!
static void SendRawMessage(const char* msg);
/*******************************************************************************
* Add new menu entries to parent. If parent is "", the entry gets added to the
* main menubar (toplevel).
*******************************************************************************/
// This adds a new submenu to the menubar.
void MenuItem(const char* parent, const char* name);
// This adds a new (normal) menu entry with an associated eventID, which should
// be unique among menubar eventIDs.
void MenuItem(const char* parent, const char* name, int cmdEvent);
// This adds a new checkbox entry, which might initally be flagged.
void MenuItem(const char* parent, const char* name,
int cmdEvent, bool flagged);
// This adds a new popup submenu to the popup menu. If parent is "", the entry
// gets added at "toplevel" popupmenu.
void PopupItem(const char* parent, const char* name);
// This adds a new popup entry with the associated eventID, which should be
// unique among popup eventIDs.
// If value and desc are given, on a click the server will ask you to modify
// the value and return the new value.
void PopupItem(const char* parent, const char* name,
int cmdEvent, const char* value, const char* desc);
// Returns the correct Y coordinate for a window, depending on whether it might
// have to be flipped (by ySize).
int TranslateYCoordinate(int y);
private:
#ifdef HAVE_LIBLEPT
// Transfers a binary Image.
void TransferBinaryImage(struct Pix* image);
// Transfers a gray scale Image.
void TransferGrayImage(struct Pix* image);
// Transfers a 32-Bit Image.
void Transfer32bppImage(struct Pix* image);
#endif
// Sets up ScrollView, depending on the variables from the constructor.
void Initialize(const char* name, int x_pos, int y_pos, int x_size,
int y_size, int x_canvas_size, int y_canvas_size,
bool y_axis_reversed, const char* server_name);
// Start the message receiving thread.
static void* MessageReceiver(void* a);
// Place an event into the event_table (synchronized).
void SetEvent(SVEvent* svevent);
// Wake up the semaphore.
void Signal();
// Returns the unique, shared network stream.
static SVNetwork* GetStream() { return stream_; }
// Starts a new event handler. Called whenever a new window is created.
static void* StartEventHandler(void* sv);
// Escapes the ' character with a \, so it can be processed by LUA.
char* AddEscapeChars(const char* input);
// The event handler for this window.
SVEventHandler* event_handler_;
// The name of the window.
const char* window_name_;
// The id of the window.
int window_id_;
// The points last set by setCursor(x,y) or then updated by drawTo(x,y).
int current_position_x_, current_position_y_;
// Whether the axis is reversed.
bool y_axis_is_reversed_;
// If the y axis is reversed, flip all y values by ySize.
int y_size_;
// # of created windows (used to assign an id to each ScrollView* for svmap).
static int nr_created_windows_;
// The stream through which the c++ client is connected to the server.
static SVNetwork* stream_;
// Table of all the currently queued events.
SVEvent* event_table_[SVET_COUNT];
// Mutex to access the event_table_ in a synchronized fashion.
SVMutex* mutex_;
// Semaphore to the thread belonging to this window.
SVSemaphore* semaphore_;
};
#endif // THIRD_PARTY_TESSERACT_VIEWER_SCROLLVIEW_H__

View File

@ -1,84 +0,0 @@
/**********************************************************************
* File: showimg.c (Formerly showim.c)
* Description: Interface to sbdaemon for displaying images.
* Author: Ray Smith
* Created: Mon Jun 11 16:20:34 BST 1990
*
* (C) Copyright 1990, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#include "mfcpch.h"
#include "grphshm.h"
#include "showim.h"
void (*show_func) (IMAGE *, INT32, INT32, INT32, INT32, WINDOW, INT32,
INT32) = def_show_sub_image;
/**********************************************************************
* show_sub_image
*
* Send the given image to the daemon and insert it in the display list.
**********************************************************************/
DLLSYM void def_show_sub_image( //show this image
IMAGE *source, //image to show
INT32 xstart, //start coords
INT32 ystart,
INT32 xext, //extent to show
INT32 yext,
WINDOW win, //window to draw in
INT32 xpos, //position to show at
INT32 ypos //y position
) {
EIGHTOP *newop; //message structure
INT32 y; //y coord
INT32 linelength; //bytes per line
IMAGE dummyimage; //used for copying to
IMAGEOP *sendline; //transmitted line
INT32 structsize; //size of structure
INT32 destbpp; //destination bits per pixel
destbpp = source->get_bpp (); //send all images unchanged
newop = (EIGHTOP *) getshm (sizeof (EIGHTOP));
if (newop != NULL) {
//send the fd
newop->header.fd = win->get_fd ();
newop->type = SHOWIMAGE; //send the operator
newop->param.p[0].i = xext; //send parameters
newop->param.p[1].i = yext;
newop->param.p[2].i = destbpp;
newop->param.p[3].i = xpos;
newop->param.p[4].i = ypos;
//bytes required
linelength = COMPUTE_IMAGE_XDIM (xext, destbpp);
linelength++; //round up to next
linelength &= ~1; //multiple of 2
//size of structure
structsize = (INT32) (sizeof (IMAGEOP) + linelength - 2);
for (y = yext - 1; y >= 0; --y) {
//get space
sendline = (IMAGEOP *) getshm (structsize);
if (sendline != NULL) {
sendline->header.fd = win->get_fd ();
sendline->type = SHOWLINE;
sendline->size = structsize;
dummyimage.capture (sendline->line, xext, 1, (INT8) destbpp);
//ready for copy
//copy to shm
copy_sub_image (source, xstart, ystart + y, xext, 1, &dummyimage, 0, 0, FALSE);
}
}
}
}

View File

@ -1,41 +0,0 @@
/**********************************************************************
* File: showimg.c (Formerly showim.c)
* Description: Interface to sbdaemon for displaying images.
* Author: Ray Smith
* Created: Mon Jun 11 16:20:34 BST 1990
*
* (C) Copyright 1990, Hewlett-Packard Ltd.
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
** http://www.apache.org/licenses/LICENSE-2.0
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*
**********************************************************************/
#ifndef SHOWIM_H
#define SHOWIM_H
#include "grphics.h"
#include "img.h"
#define show_sub_image(im,xstart,ystart,xext,yext,win,xpos,ypos) (*show_func)(im,xstart,ystart,xext,yext,win,xpos,ypos)
extern void (*show_func) (IMAGE *, INT32, INT32, INT32, INT32, WINDOW, INT32,
INT32);
DLLSYM void def_show_sub_image( //show this image
IMAGE *source, //image to show
INT32 xstart, //start coords
INT32 ystart,
INT32 xext, //extent to show
INT32 yext,
WINDOW win, //window to draw in
INT32 xpos, //position to show at
INT32 ypos //y position
);
#endif

134
viewer/svmnode.cpp Normal file
View File

@ -0,0 +1,134 @@
///////////////////////////////////////////////////////////////////////
// File: svmnode.cpp
// description_: ScrollView Menu Node
// Author: Joern Wanke
// Created: Thu Nov 29 2007
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// A SVMenuNode is an entity which contains the mapping from a menu entry on
// the server side to the corresponding associated commands on the client.
// It is designed to be a tree structure with a root node, which can then be
// used to generate the appropriate messages to the server to display the
// menu structure there.
// A SVMenuNode can both be used in the context_ of popup menus as well as
// menu bars.
#include "svmnode.h"
#include <iostream>
#include "scrollview.h"
// Create the empty root menu node. with just a caption. All other nodes should
// be added to this or one of the submenus.
SVMenuNode::SVMenuNode() {
cmd_event_ = -1;
text_ = NULL;
child_ = NULL;
next_ = NULL;
parent_ = NULL;
toggle_value_ = false;
is_check_box_entry_ = false;
value_ = NULL;
description_ = NULL;
}
SVMenuNode::~SVMenuNode() {
delete[] text_;
// delete[] description_;
}
// Create a new sub menu node with just a caption. This is used to create
// nodes which act as parent nodes to other nodes (e.g. submenus).
SVMenuNode* SVMenuNode::AddChild(const char* txt) {
SVMenuNode* s = new SVMenuNode(-1, txt, false, false, NULL, NULL);
this->AddChild(s);
return s;
}
// Create a "normal" menu node which is associated with a command event.
void SVMenuNode::AddChild(const char* txt, int command_event) {
this->AddChild(new SVMenuNode(command_event, txt, false, false, NULL, NULL));
}
// Create a menu node with an associated value (which might be changed
// through the gui).
void SVMenuNode::AddChild(const char* txt, int command_event,
const char* val) {
this->AddChild(new SVMenuNode(command_event, txt, false, false, val, NULL));
}
// Create a menu node with an associated value and description_.
void SVMenuNode::AddChild(const char* txt, int command_event, const char* val,
const char* desc) {
this->AddChild(new SVMenuNode(command_event, txt, false, false, val, desc));
}
// Create a flag menu node.
void SVMenuNode::AddChild(const char* txt, int command_event, int tv) {
this->AddChild(new SVMenuNode(command_event, txt, tv, true, NULL, NULL));
}
// Convenience function called from the different constructors to initialize
// the different values of the menu node.
SVMenuNode::SVMenuNode(int command_event, const char* txt,
int tv, bool check_box_entry, const char* val,
const char* desc) {
cmd_event_ = command_event;
text_ = new char[strlen(txt) + 1];
strncpy(text_, txt, strlen(txt));
text_[strlen(txt)] = '\0';
value_ = val;
description_ = desc;
child_ = NULL;
next_ = NULL;
parent_ = NULL;
toggle_value_ = tv;
is_check_box_entry_ = check_box_entry;
}
// Add a child node to this menu node.
void SVMenuNode::AddChild(SVMenuNode* svmn) {
svmn->parent_ = this;
// No children yet.
if (child_ == NULL) {
child_ = svmn;
} else {
SVMenuNode* cur = child_;
while (cur->next_ != NULL) { cur = cur->next_; }
cur->next_ = svmn;
}
}
// Build a menu structure for the server and send the necessary messages.
// Should be called on the root node. If menu_bar is true, a menu_bar menu
// is built (e.g. on top of the window), if it is false a popup menu is
// built which gets shown by right clicking on the window.
// Deletes itself afterwards.
void SVMenuNode::BuildMenu(ScrollView* sv, bool menu_bar) {
if ((parent_ != NULL) && (menu_bar)) {
if (is_check_box_entry_) {
sv->MenuItem(parent_->text_, text_, cmd_event_, toggle_value_);
} else { sv->MenuItem(parent_->text_, text_, cmd_event_); }
} else if ((parent_ != NULL) && (!menu_bar)) {
if (description_ != NULL) { sv->PopupItem(parent_->text_, text_,
cmd_event_, value_, description_);
} else { sv->PopupItem(parent_->text_, text_); }
}
if (child_ != NULL) { child_->BuildMenu(sv, menu_bar); delete child_; }
if (next_ != NULL) { next_->BuildMenu(sv, menu_bar); delete next_; }
}

94
viewer/svmnode.h Normal file
View File

@ -0,0 +1,94 @@
///////////////////////////////////////////////////////////////////////
// File: svmnode.h
// description_: ScrollView Menu Node
// Author: Joern Wanke
// Created: Thu Nov 29 2007
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// A SVMenuNode is an entity which contains the mapping from a menu entry on
// the server side to the corresponding associated commands on the client.
// It is designed to be a tree structure with a root node, which can then be
// used to generate the appropriate messages to the server to display the
// menu structure there.
// A SVMenuNode can both be used in the context_ of popup menus as well as
// menu bars.
#ifndef THIRD_PARTY_TESSERACT_VIEWER_SVMNODE_H__
#define THIRD_PARTY_TESSERACT_VIEWER_SVMNODE_H__
class ScrollView;
class SVMenuNode {
public:
// Creating the (empty) root menu node.
SVMenuNode();
// Destructor for every node.
~SVMenuNode();
// Create a new sub menu node with just a caption. This is used to create
// nodes which act as parent nodes to other nodes (e.g. submenus).
SVMenuNode* AddChild(const char* txt);
// Create a "normal" menu node which is associated with a command event.
void AddChild(const char* txt, int command_event);
// Create a flag menu node.
void AddChild(const char* txt, int command_event, int tv);
// Create a menu node with an associated value (which might be changed
// through the gui).
void AddChild(const char* txt, int command_event, const char* val);
// Create a menu node with an associated value and description_.
void AddChild(const char* txt, int command_event,
const char* val, const char* desc);
// Build a menu structure for the server and send the necessary messages.
// Should be called on the root node. If menu_bar is true, a menu_bar menu
// is built (e.g. on top of the window), if it is false a popup menu is
// built which gets shown by right clicking on the window.
void BuildMenu(ScrollView *sv, bool menu_bar = true);
private:
// Constructor holding the actual node data.
SVMenuNode(int command_event, const char* txt, int tv,
bool check_box_entry, const char* val, const char* desc);
// Adds a new menu node to the current node.
void AddChild(SVMenuNode* svmn);
// The parent node of this node.
SVMenuNode* parent_;
// The first child of this node.
SVMenuNode* child_;
// The next "sibling" of this node (e.g. same parent).
SVMenuNode* next_;
// Whether this menu node actually is a flag.
bool is_check_box_entry_;
// The command event associated with a specific menu node. Should be unique.
int cmd_event_;
// The caption associated with a specific menu node.
char* text_;
// The value of the flag (if this menu node is a flag).
bool toggle_value_;
// The value of the menu node. (optional)
const char* value_;
// A description_ of the value. (optional)
const char* description_;
};
#endif // THIRD_PARTY_TESSERACT_VIEWER_SVMNODE_H__

220
viewer/svpaint.cpp Normal file
View File

@ -0,0 +1,220 @@
// Copyright 2007 Google Inc. All Rights Reserved.
//
// Author: Joern Wanke
//
// Simple drawing program to illustrate ScrollView capabilities.
//
// Functionality:
// - The menubar is used to select from different sample styles of input.
// - With the RMB it is possible to change the RGB values in different
// popup menus.
// - A LMB click either draws point-to-point, point or text.
// - A LMB dragging either draws a line, a rectangle or ellipse.
#include "scrollview.h"
#include "svmnode.h"
#include <stdlib.h>
#include <iostream>
// The current color values we use, initially white (== ScrollView::WHITE).
int rgb[3] = { 255, 255, 255 };
class SVPaint : public SVEventHandler {
public:
SVPaint(const char* server_name);
// This is the main event handling function that we need to overwrite, defined
// in SVEventHandler.
void Notify(const SVEvent* sv_event);
private:
// The Handler take care of the SVET_POPUP, SVET_MENU, SVET_CLICK and
// SVET_SELECTION events.
void PopupHandler(const SVEvent* sv_event);
void MenuBarHandler(const SVEvent* sv_event);
void ClickHandler(const SVEvent* sv_event);
void SelectionHandler(const SVEvent* sv_event);
// Convenience functions to build little menus.
SVMenuNode* BuildPopupMenu();
SVMenuNode* BuildMenuBar();
// Our window.
ScrollView* window_;
// The mode we are in when an SVET_CLICK or an SVET_SELECTION event occurs.
int click_mode_;
int drag_mode_;
// In the point-to-point drawing mode, we need to set a start-point the first
// time we call it (e.g. call SetCursor).
bool has_start_point_;
};
// Build a sample popup menu.
SVMenuNode* SVPaint::BuildPopupMenu() {
SVMenuNode* root = new SVMenuNode(); // Empty root node
// Initial color is white, so we all values to 255.
root->AddChild("R", // Shown caption.
1, // assoc. command_id.
"255", // initial value.
"Red Color Value?"); // Shown description.
root->AddChild("G", 2, "255", "Green Color Value?");
root->AddChild("B", 3, "255", "Blue Color Value?");
return root;
}
// Build a sample menu bar.
SVMenuNode* SVPaint::BuildMenuBar() {
SVMenuNode* root = new SVMenuNode(); // Empty root node
// Create some submenus and add them to the root.
SVMenuNode* click = root->AddChild("Clicking");
SVMenuNode* drag = root->AddChild("Dragging");
// Put some nodes into the submenus.
click->AddChild("Point to Point Drawing", // Caption.
1); // command_id.
click->AddChild("Point Drawing", 2);
click->AddChild("Text Drawing", 3);
drag->AddChild("Line Drawing", 4);
drag->AddChild("Rectangle Drawing", 5);
drag->AddChild("Ellipse Drawing", 6);
return root;
}
// Takes care of the SVET_POPUP events.
// In our case, SVET_POPUP is used to set RGB values.
void SVPaint::PopupHandler(const SVEvent* sv_event) {
// Since we only have the RGB values as popup items,
// we take a shortcut to not bloat up code:
rgb[sv_event->command_id - 1] = atoi(sv_event->parameter);
window_->Pen(rgb[0], rgb[1], rgb[2]);
}
// Takes care of the SVET_MENU events.
// In our case, we change either the click_mode_ (commands 1-3)
// or the drag_mode_ (commands 4-6).
void SVPaint::MenuBarHandler(const SVEvent* sv_event) {
if ((sv_event->command_id > 0) && (sv_event->command_id < 4)) {
click_mode_ = sv_event->command_id;
has_start_point_ = false;
} else { drag_mode_ = sv_event->command_id; }
}
// Takes care of the SVET_CLICK events.
// Depending on the click_mode_ we are in, either do Point-to-Point drawing,
// point drawing, or draw text.
void SVPaint::ClickHandler(const SVEvent* sv_event) {
switch (click_mode_) {
case 1: //Point to Point
if (has_start_point_) { window_->DrawTo(sv_event->x, sv_event->y);
} else {
has_start_point_ = true;
window_->SetCursor(sv_event->x, sv_event->y);
}
break;
case 2: //Point Drawing..simulated by drawing a 1 pixel line.
window_->Line(sv_event->x, sv_event->y, sv_event->x, sv_event->y);
break;
case 3: //Text
// We show a modal input dialog on our window, then draw the input and
// finally delete the input pointer.
char* p = window_->ShowInputDialog("Text:");
window_->Text(sv_event->x, sv_event->y, p);
delete p;
break;
}
}
// Takes care of the SVET_SELECTION events.
// Depending on the drag_mode_ we are in, either draw a line, a rectangle or
// an ellipse.
void SVPaint::SelectionHandler(const SVEvent* sv_event) {
switch (drag_mode_) {
//FIXME inversed x_size, y_size
case 4: //Line
window_->Line(sv_event->x, sv_event->y,
sv_event->x - sv_event->x_size,
sv_event->y - sv_event->y_size);
break;
case 5: //Rectangle
window_->Rectangle(sv_event->x, sv_event->y,
sv_event->x - sv_event->x_size,
sv_event->y - sv_event->y_size);
break;
case 6: //Ellipse
window_->Ellipse(sv_event->x - sv_event->x_size,
sv_event->y - sv_event->y_size,
sv_event->x_size, sv_event->y_size);
break;
}
}
// The event handling function from ScrollView which we have to overwrite.
// We handle CLICK, SELECTION, MENU and POPUP and throw away all other events.
void SVPaint::Notify(const SVEvent* sv_event) {
if (sv_event->type == SVET_CLICK) { ClickHandler(sv_event); }
else if (sv_event->type == SVET_SELECTION) { SelectionHandler(sv_event); }
else if (sv_event->type == SVET_MENU) { MenuBarHandler(sv_event); }
else if (sv_event->type == SVET_POPUP) { PopupHandler(sv_event); }
else {} //throw other events away
}
// Builds a new window, initializes the variables and event handler and builds
// the menu.
SVPaint::SVPaint(const char *server_name) {
window_ = new ScrollView("ScrollView Paint Example", // window caption
0, 0, // x,y window position
500, 500, // window size
500, 500, // canvas size
false, // whether the Y axis is inversed.
// this is included due to legacy
// reasons for tesseract and enables
// us to have (0,0) as the LOWER left
// of the coordinate system.
server_name); // the server address.
// Set the start modes to point-to-point and line drawing.
click_mode_ = 1;
drag_mode_ = 4;
has_start_point_ = false;
// Bild our menus and add them to the window. The flag illustrates whether
// this is a menu bar.
SVMenuNode* popup_menu = BuildPopupMenu();
popup_menu->BuildMenu(window_,false);
SVMenuNode* bar_menu = BuildMenuBar();
bar_menu->BuildMenu(window_,true);
// Set the initial color values to White (could also be done by
// passing (rgb[0], rgb[1], rgb[2]).
window_->Pen(ScrollView::WHITE);
window_->Brush(ScrollView::WHITE);
// Adds the event handler to the window. This actually ensures that Notify
// gets called when events occur.
window_->AddEventHandler(this);
// Set the window visible (calling this is important to actually render
// everything. Without this call, the window would also be drawn, but the
// menu bars would be missing.
window_->SetVisible(true);
// Rest this thread until its window is destroyed.
// Note that a special eventhandling thread was created when constructing
// the window. Due to this, the application will not deadlock here.
window_->AwaitEvent(SVET_DESTROY);
// We now have 3 Threads running:
// (1) The MessageReceiver thread which fetches messages and distributes them
// (2) The EventHandler thread which handles all events for window_
// (3) The main thread which waits on window_ for a DESTROY event (blocked)
}
// If a parameter is given, we try to connect to the given server.
// This enables us to test the remote capabilites of ScrollView.
int main(int argc, char** argv) {
const char* server_name;
if (argc > 1) { server_name = argv[1]; } else { server_name = "localhost"; }
SVPaint svp(server_name);
}

323
viewer/svutil.cpp Normal file
View File

@ -0,0 +1,323 @@
///////////////////////////////////////////////////////////////////////
// File: svutil.cpp
// Description: ScrollView Utilities
// Author: Joern Wanke
// Created: Thu Nov 29 2007
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// SVUtil contains the SVSync and SVNetwork classes, which are used for
// thread/process creation & synchronization and network connection.
#include "svutil.h"
#ifdef WIN32
#include <windows.h>
#include <winsock.h>
#else
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <netdb.h>
#include <sys/socket.h>
#endif
#include <iostream>
#include <string>
const int kBufferSize = 65536;
const int kMaxMsgSize = 4096;
// Signals a thread to exit.
void SVSync::ExitThread() {
#ifdef WIN32
//ExitThread(0);
#else
pthread_exit(0);
#endif
}
// Starts a new process.
void SVSync::StartProcess(const char* executable, const char* args) {
#ifdef WIN32
std::string proc;
proc.append(executable);
proc.append(" ");
proc.append(args);
std::cout << "Starting " << proc << std::endl;
CreateProcess(NULL, (LPWSTR) proc.c_str(), NULL,
NULL, FALSE, 0, NULL, NULL, NULL, NULL);
#else
int pid = fork();
if (pid != 0) { // The father process returns
} else {
char* mutable_args = strdup(args);
int argc = 1;
for (int i = 0; mutable_args[i]; ++i) {
if (mutable_args[i] == ' ') {
++argc;
}
}
char** argv = new char*[argc + 2];
argv[0] = strdup(executable);
argv[1] = mutable_args;
argc = 2;
bool inquote = false;
for (int i = 0; mutable_args[i]; ++i) {
if (!inquote && mutable_args[i] == ' ') {
mutable_args[i] = '\0';
argv[argc++] = mutable_args + i + 1;
} else if (mutable_args[i] == '"') {
inquote = !inquote;
mutable_args[i] = ' ';
}
}
argv[argc] = NULL;
execvp(executable, argv);
}
#endif
}
SVSemaphore::SVSemaphore() {
#ifdef WIN32
semaphore_ = CreateSemaphore(0, 0, 10, 0);
#else
sem_init(&semaphore_, 0, 0);
#endif
}
void SVSemaphore::Signal() {
#ifdef WIN32
ReleaseSemaphore(semaphore_, 1, NULL);
#else
sem_post(&semaphore_);
#endif
}
void SVSemaphore::Wait() {
#ifdef WIN32
WaitForSingleObject(semaphore_, INFINITE);
#else
sem_wait(&semaphore_);
#endif
}
SVMutex::SVMutex() {
#ifdef WIN32
mutex_ = CreateMutex(0, FALSE, 0);
#else
pthread_mutex_init(&mutex_, NULL);
#endif
}
void SVMutex::Lock() {
#ifdef WIN32
WaitForSingleObject(mutex_, INFINITE);
#else
pthread_mutex_lock(&mutex_);
#endif
}
void SVMutex::Unlock() {
#ifdef WIN32
ReleaseMutex(mutex_);
#else
pthread_mutex_unlock(&mutex_);
#endif
}
// Create new thread.
int SVSync::StartThread(void *(*func)(void*), void* arg) {
#ifdef WIN32
LPTHREAD_START_ROUTINE f = (LPTHREAD_START_ROUTINE) func;
DWORD threadid;
HANDLE newthread = CreateThread(
NULL, // default security attributes
0, // use default stack size
f, // thread function
arg, // argument to thread function
0, // use default creation flags
&threadid); // returns the thread identifier
return threadid;
#else
pthread_t helper;
pthread_create(&helper, NULL, func, arg);
return helper;
#endif
}
// Place a message in the message buffer (and flush it).
void SVNetwork::Send(const char* msg) {
mutex_send_->Lock();
msg_buffer_out_.append(msg);
mutex_send_->Unlock();
}
// Send the whole buffer.
void SVNetwork::Flush() {
mutex_send_->Lock();
while (msg_buffer_out_.size() > 0) {
int i = send(stream_, msg_buffer_out_.c_str(), msg_buffer_out_.length(), 0);
msg_buffer_out_.erase(0, i);
}
mutex_send_->Unlock();
}
// Receive a message from the server.
// This will always return one line of char* (denoted by \n).
char* SVNetwork::Receive() {
char* result = NULL;
#ifdef WIN32
if (has_content) { result = strtok (NULL, "\n"); }
#else
if (buffer_ptr_ != NULL) { result = strtok_r(NULL, "\n", &buffer_ptr_); }
#endif
// This means there is something left in the buffer and we return it.
if (result != NULL) { return result;
// Otherwise, we read from the stream_.
} else {
buffer_ptr_ = NULL;
has_content = false;
// The timeout length is not really important since we are looping anyway
// until a new message is delivered.
struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;
// Set the flags to return when the stream_ is ready to be read.
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(stream_, &readfds);
int i = select(stream_+1, &readfds, NULL, NULL, &tv);
// The stream_ died.
if (i == 0) { return NULL; }
// Read the message buffer.
i = recv(stream_, msg_buffer_in_, kMaxMsgSize, 0);
// Server quit (0) or error (-1).
if (i <= 0) { return NULL; }
msg_buffer_in_[i] = '\0';
has_content = true;
#ifdef WIN32
return strtok(msg_buffer_in_,"\n");
#else
// Setup a new string tokenizer.
return strtok_r(msg_buffer_in_, "\n", &buffer_ptr_);
#endif
}
}
// Close the connection to the server.
void SVNetwork::Close() {
#ifdef WIN32
closesocket(stream_);
#else
close(stream_);
#endif
}
// Set up a connection to hostname on port.
SVNetwork::SVNetwork(const char* hostname, int port) {
mutex_send_ = new SVMutex();
struct sockaddr_in address;
struct hostent *name;
msg_buffer_in_ = new char[kMaxMsgSize + 1];
msg_buffer_in_[0] = '\0';
has_content = false;
buffer_ptr_ = NULL;
// Get the host data depending on the OS.
#ifdef WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(1, 1), &wsaData);
name = gethostbyname(hostname);
#else
struct hostent hp;
int herr;
char buffer[kBufferSize];
gethostbyname_r(hostname, &hp, buffer, kBufferSize, &name, &herr);
#endif
// Fill in the appropriate variables to be able to connect to the server.
address.sin_family = name->h_addrtype;
memcpy((char *) &address.sin_addr.s_addr,
name->h_addr_list[0], name->h_length);
address.sin_port = htons(port);
stream_ = socket(AF_INET, SOCK_STREAM, 0);
// If server is not there, we will start a new server as local child process.
if (connect(stream_, (struct sockaddr *) &address, sizeof(address)) < 0) {
const char* scrollview_path = getenv("SCROLLVIEW_PATH");
if (scrollview_path == NULL) {
#ifdef SCROLLVIEW_PATH
#define _STR(a) #a
#define _XSTR(a) _STR(a)
scrollview_path = _XSTR(SCROLLVIEW_PATH);
#undef _XSTR
#undef _STR
#else
scrollview_path = ".";
#endif
}
#ifdef WIN32
const char* prog = "java";
const char* cmd_template =
#else
const char* prog = "sh";
const char* cmd_template = "-c \"java "
#endif
"-Djava.library.path=%s -cp %s/luajava-1.1.jar:%s/ScrollView.jar:"
"%s/piccolo-1.2.jar:%s/piccolox-1.2.jar"
" com.google.scrollview.ScrollView"
#ifdef WIN32
;
#else
" >/dev/null 2>&1\"";
#endif
int cmdlen = strlen(cmd_template) + 5*strlen(scrollview_path) + 1;
char* cmd = new char[cmdlen];
snprintf(cmd, cmdlen, cmd_template, scrollview_path, scrollview_path,
scrollview_path, scrollview_path, scrollview_path);
SVSync::StartProcess(prog, cmd);
delete [] cmd;
// Wait for server to show up.
// Note: There is no exception handling in case the server never turns up.
while (connect(stream_, (struct sockaddr *) &address,
sizeof(address)) < 0) {
std::cout << "ScrollView: Waiting for server...\n";
#ifdef WIN32
Sleep(1000);
#else
sleep(1);
#endif
}
}
}
SVNetwork::~SVNetwork() {
delete[] msg_buffer_in_;
delete mutex_send_;
}

124
viewer/svutil.h Normal file
View File

@ -0,0 +1,124 @@
///////////////////////////////////////////////////////////////////////
// File: svutil.h
// Description: ScrollView Utilities
// Author: Joern Wanke
// Created: Thu Nov 29 2007
//
// (C) Copyright 2007, Google Inc.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////
//
// SVUtil contains the SVSync, SVSemaphore, SVMutex and SVNetwork
// classes, which are used for thread/process creation & synchronization
// and network connection.
#ifndef THIRD_PARTY_TESSERACT_VIEWER_SVUTIL_H__
#define THIRD_PARTY_TESSERACT_VIEWER_SVUTIL_H__
#ifdef WIN32
#include <windows.h>
#else
#include <pthread.h>
#include <semaphore.h>
#endif
#include <string>
// The SVSync class provides functionality for Thread & Process Creation
class SVSync {
public:
// Create new thread.
static int StartThread(void *(*func)(void*), void* arg);
// Signals a thread to exit.
static void ExitThread();
// Starts a new process.
static void StartProcess(const char* executable, const char* args);
};
// A semaphore class which encapsulates the main signalling
// and wait abilities of semaphores for windows and unix.
class SVSemaphore {
public:
// Sets up a semaphore.
SVSemaphore();
// Signal a semaphore.
void Signal();
// Wait on a semaphore.
void Wait();
private:
#ifdef WIN32
HANDLE semaphore_;
#else
sem_t semaphore_;
#endif
};
// A mutex which encapsulates the main locking and unlocking
// abilites of mutexes for windows and unix.
class SVMutex {
public:
// Sets up a new mutex.
SVMutex();
// Locks on a mutex.
void Lock();
// Unlocks on a mutex.
void Unlock();
private:
#ifdef WIN32
HANDLE mutex_;
#else
pthread_mutex_t mutex_;
#endif
};
// The SVNetwork class takes care of the remote connection for ScrollView
// This means setting up and maintaining a remote connection, sending and
// receiving messages and closing the connection.
// It is designed to work on both Linux and Windows.
class SVNetwork {
public:
// Set up a connection to hostname on port.
SVNetwork(const char* hostname, int port);
// Destructor.
~SVNetwork();
// Put a message in the messagebuffer to the server and try to send it.
void Send(const char* msg);
// Receive a message from the server.
// This will always return one line of char* (denoted by \n).
char* Receive();
// Close the connection to the server.
void Close();
// Flush the buffer.
void Flush();
private:
// The mutex for access to Send() and Flush().
SVMutex* mutex_send_;
// The actual stream_ to the server.
int stream_;
// Stores the last received message-chunk from the server.
char* msg_buffer_in_;
// Stores the messages which are supposed to go out.
std::string msg_buffer_out_;
bool has_content; // Win32 (strtok)
// Where we are at in our msg_buffer_in_
char* buffer_ptr_; // Unix (strtok_r)
};
#endif // THIRD_PARTY_TESSERACT_VIEWER_SVUTIL_H__