mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
634 lines
14 KiB
C++
634 lines
14 KiB
C++
|
/*
|
||
|
* $Logfile: /DescentIII/Main/linux/lnxmono.cpp $
|
||
|
* $Revision: 1.3 $
|
||
|
* $Date: 2004/02/23 03:03:48 $
|
||
|
* $Author: ryan $
|
||
|
*
|
||
|
* Linux monochrome routines
|
||
|
*
|
||
|
* $Log: lnxmono.cpp,v $
|
||
|
* Revision 1.3 2004/02/23 03:03:48 ryan
|
||
|
* Patched to compile with gcc3 and a modern linux distro...
|
||
|
*
|
||
|
* Revision 1.2 2000/05/29 05:39:59 icculus
|
||
|
* Changed some exit() calls to _exit().
|
||
|
*
|
||
|
* Revision 1.1.1.1 2000/04/18 00:00:39 icculus
|
||
|
* initial checkin
|
||
|
*
|
||
|
*
|
||
|
* 13 8/22/99 5:52a Jeff
|
||
|
* remote monochrome server code added
|
||
|
*
|
||
|
* 12 7/14/99 9:09p Jeff
|
||
|
* added comment header
|
||
|
*
|
||
|
* $NoKeywords: $
|
||
|
*/
|
||
|
|
||
|
#include "debug.h"
|
||
|
#include <assert.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <memory.h>
|
||
|
#include <signal.h>
|
||
|
|
||
|
// -------- Start TCP/IP Mono Logging Section
|
||
|
#include <sys/socket.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <sys/time.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <arpa/inet.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
#include <errno.h>
|
||
|
|
||
|
#define MAX_TCPLOG_LEN 2000
|
||
|
#define SOCKET int
|
||
|
#define SOCKADDR_IN sockaddr_in
|
||
|
#define SOCKADDR sockaddr
|
||
|
#define INVALID_SOCKET -1
|
||
|
static SOCKET tcp_log_sock;
|
||
|
static struct sockaddr_in tcp_log_addr;
|
||
|
static char tcp_log_buffer[MAX_TCPLOG_LEN];
|
||
|
static int Console_fd = -1;
|
||
|
static bool Mono_initialized = 0;
|
||
|
static bool Mono_use_real = false;
|
||
|
static bool Mono_use_window_remote = false;
|
||
|
static int Debug_logfile = 0;
|
||
|
bool Debug_print_block = false;
|
||
|
#define min(a,b) ((a<b)?a:b)
|
||
|
|
||
|
// ===============================
|
||
|
// pthread library functions
|
||
|
// ===============================
|
||
|
#include <pthread.h>
|
||
|
#include <dlfcn.h>
|
||
|
|
||
|
#if DLOPEN_PTHREAD
|
||
|
typedef int (*pthread_create_fp)(pthread_t *__thread,__const pthread_attr_t *__attr,void *(*__start_routine) (void *),void *__arg);
|
||
|
typedef int (*pthread_detach_fp)(pthread_t __th);
|
||
|
typedef pthread_t (*pthread_self_fp)(void);
|
||
|
|
||
|
static pthread_create_fp dpthread_create = NULL;
|
||
|
static pthread_detach_fp dpthread_detach = NULL;
|
||
|
static pthread_self_fp dpthread_self = NULL;
|
||
|
#else
|
||
|
#define dpthread_create pthread_create
|
||
|
#define dpthread_detach pthread_detach
|
||
|
#define dpthread_self pthread_self
|
||
|
#endif
|
||
|
|
||
|
static unsigned long long Timer_sys_start_time = 0;
|
||
|
static unsigned long long Timer_accum = 0,Timer_high_mark = 0;
|
||
|
|
||
|
static float nw_TCPLoggingTimer(void)
|
||
|
{
|
||
|
unsigned long time_ms;
|
||
|
unsigned long long ret;
|
||
|
|
||
|
struct timeval t;
|
||
|
gettimeofday(&t,NULL);
|
||
|
|
||
|
ret = (unsigned long long)t.tv_sec*1000000.0 + t.tv_usec;
|
||
|
|
||
|
if(ret > Timer_high_mark)
|
||
|
{
|
||
|
Timer_high_mark = ret;
|
||
|
}else
|
||
|
{
|
||
|
// timer roll over
|
||
|
if(Timer_high_mark>0)
|
||
|
Timer_accum += (Timer_high_mark - Timer_sys_start_time);
|
||
|
Timer_high_mark = ret;
|
||
|
Timer_sys_start_time = ret;
|
||
|
ret = 100;//give some time
|
||
|
}
|
||
|
|
||
|
time_ms = Timer_accum + ret - Timer_sys_start_time;
|
||
|
|
||
|
return (float)((double)time_ms/((double)1000000.0));
|
||
|
}
|
||
|
|
||
|
static bool nw_TCPLoggingTimer_Init(void)
|
||
|
{
|
||
|
struct timeval t;
|
||
|
gettimeofday(&t,NULL);
|
||
|
|
||
|
Timer_sys_start_time = (unsigned long long)t.tv_sec*1000000.0 + t.tv_usec;
|
||
|
Timer_accum = 0;
|
||
|
Timer_high_mark = 0;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static unsigned char outgoing_mono_packet[512];
|
||
|
static volatile int outgoing_packet_size = 0;
|
||
|
static volatile float outgoing_last_time_sent = 0;
|
||
|
static volatile bool outgoing_packet_flush = false;
|
||
|
static volatile bool outgoing_building_packet = false;
|
||
|
|
||
|
void *nw_TCPLoggingWorker(void *arg)
|
||
|
{
|
||
|
dpthread_detach(dpthread_self());
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
if(tcp_log_sock==INVALID_SOCKET)
|
||
|
break;
|
||
|
|
||
|
fd_set wfds;
|
||
|
timeval timeout = {0,0};
|
||
|
|
||
|
FD_ZERO(&wfds);
|
||
|
FD_SET(tcp_log_sock, &wfds );
|
||
|
|
||
|
int sock_writable = select(tcp_log_sock+1, NULL, &wfds, NULL, &timeout);
|
||
|
|
||
|
if ( sock_writable == -1 )
|
||
|
{
|
||
|
fprintf(stdout,"Error blocking on Monochrome server port\n");
|
||
|
_exit(1);
|
||
|
}
|
||
|
|
||
|
if(!sock_writable)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if(outgoing_packet_size==0)
|
||
|
continue;
|
||
|
if(outgoing_building_packet)
|
||
|
continue;
|
||
|
|
||
|
int save_size = outgoing_packet_size;
|
||
|
outgoing_packet_size = -1;//this informs the other thread that we are sending
|
||
|
|
||
|
float curr_time = nw_TCPLoggingTimer();
|
||
|
if(curr_time>(outgoing_last_time_sent+0.05f))
|
||
|
{
|
||
|
//time to send the packet
|
||
|
outgoing_last_time_sent = curr_time;
|
||
|
|
||
|
send(tcp_log_sock,outgoing_mono_packet,save_size,0);
|
||
|
|
||
|
save_size = 0;
|
||
|
}
|
||
|
|
||
|
outgoing_packet_size = save_size;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
bool nw_InitTCPLogging(char *ip,unsigned short port)
|
||
|
{
|
||
|
#if DLOPEN_PTHREAD
|
||
|
// load up the pthread library
|
||
|
void *lib = dlopen("libpthread.so",RTLD_GLOBAL|RTLD_NOW);
|
||
|
if(!lib)
|
||
|
{
|
||
|
fprintf(stdout,"Error: Unable to load libpthread.so\n");
|
||
|
_exit(1);
|
||
|
}
|
||
|
dpthread_create = (pthread_create_fp)dlsym(lib,"pthread_create");
|
||
|
dpthread_detach = (pthread_detach_fp)dlsym(lib,"pthread_detach");
|
||
|
dpthread_self = (pthread_self_fp)dlsym(lib,"pthread_self");
|
||
|
#endif
|
||
|
|
||
|
unsigned long argp = 1;
|
||
|
int addrlen = sizeof(SOCKADDR_IN);
|
||
|
tcp_log_sock = socket(AF_INET,SOCK_STREAM,0);
|
||
|
if(INVALID_SOCKET == tcp_log_sock)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
memset( &tcp_log_addr, 0, sizeof(SOCKADDR_IN) );
|
||
|
tcp_log_addr.sin_family = AF_INET;
|
||
|
tcp_log_addr.sin_addr.s_addr = INADDR_ANY;
|
||
|
tcp_log_addr.sin_port = 0;
|
||
|
|
||
|
if( bind(tcp_log_sock,(SOCKADDR*)&tcp_log_addr, sizeof (sockaddr)) )
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
tcp_log_addr.sin_addr.s_addr = inet_addr(ip);
|
||
|
tcp_log_addr.sin_port = htons(port);
|
||
|
|
||
|
fd_set write_fs;
|
||
|
FD_ZERO(&write_fs);
|
||
|
FD_SET(tcp_log_sock,&write_fs);
|
||
|
select(tcp_log_sock+1,NULL,&write_fs,NULL,NULL);
|
||
|
|
||
|
fprintf(stdout,"Connecting to monochrome server (%s:%d)...\n",ip,port);
|
||
|
|
||
|
if(connect(tcp_log_sock,(SOCKADDR *)&tcp_log_addr,addrlen))
|
||
|
{
|
||
|
int wserr;
|
||
|
wserr = errno;
|
||
|
fprintf(stdout,"Mono: Connect Failed...");
|
||
|
|
||
|
switch(wserr)
|
||
|
{
|
||
|
case EBADF:
|
||
|
fprintf(stdout,"EBADF\n");
|
||
|
break;
|
||
|
case EFAULT:
|
||
|
fprintf(stdout,"EFAULT\n");
|
||
|
break;
|
||
|
case ENOTSOCK:
|
||
|
fprintf(stdout,"ENOTSOCK\n");
|
||
|
break;
|
||
|
case EISCONN:
|
||
|
fprintf(stdout,"EISCONN\n");
|
||
|
break;
|
||
|
case ECONNREFUSED:
|
||
|
fprintf(stdout,"EREFUSED\n");
|
||
|
break;
|
||
|
case ETIMEDOUT:
|
||
|
fprintf(stdout,"ETIMEDOUT\n");
|
||
|
break;
|
||
|
case ENETUNREACH:
|
||
|
fprintf(stdout,"ENETUNREACH\n");
|
||
|
break;
|
||
|
default:
|
||
|
fprintf(stdout,"Unknown error %d\n",wserr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
fprintf(stdout,"Monochrome server connected\n");
|
||
|
|
||
|
// init the packet sent time
|
||
|
pthread_t thread;
|
||
|
nw_TCPLoggingTimer_Init();
|
||
|
outgoing_last_time_sent = nw_TCPLoggingTimer();
|
||
|
|
||
|
dpthread_create(&thread,NULL,nw_TCPLoggingWorker,NULL);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
void nw_TCPPrintf(int n, char * format, ... )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void nw_SendMonoPacket(unsigned char *data,int size)
|
||
|
{
|
||
|
if(tcp_log_sock==INVALID_SOCKET){
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(size>512)
|
||
|
{
|
||
|
fprintf(stdout,"Mono: Packet > 512 bytes\n");
|
||
|
_exit(1);
|
||
|
}
|
||
|
|
||
|
outgoing_building_packet = true;
|
||
|
while(outgoing_packet_size==-1);
|
||
|
|
||
|
if(outgoing_packet_size+size>512)
|
||
|
{
|
||
|
// crap...we need to flush
|
||
|
fd_set wfds;
|
||
|
FD_ZERO(&wfds);
|
||
|
FD_SET(tcp_log_sock, &wfds );
|
||
|
|
||
|
int sock_writable = select(tcp_log_sock+1, NULL, &wfds, NULL, NULL);
|
||
|
|
||
|
if ( sock_writable == -1 )
|
||
|
{
|
||
|
fprintf(stdout,"Error blocking on Monochrome server port\n");
|
||
|
_exit(1);
|
||
|
}
|
||
|
|
||
|
send(tcp_log_sock,outgoing_mono_packet,outgoing_packet_size,0);
|
||
|
outgoing_packet_size = 0;
|
||
|
}
|
||
|
|
||
|
memcpy(&outgoing_mono_packet[outgoing_packet_size],data,size);
|
||
|
outgoing_packet_size += size;
|
||
|
|
||
|
outgoing_building_packet = false;
|
||
|
}
|
||
|
|
||
|
// ---------------- End TCP/IP Mono Logging Section
|
||
|
|
||
|
void Debug_LogClose();
|
||
|
|
||
|
bool Debug_Logfile(const char *filename)
|
||
|
{
|
||
|
if (Debug_logfile == -1) {
|
||
|
Debug_logfile = open(filename, O_CREAT | O_WRONLY, S_IREAD | S_IWRITE);
|
||
|
if (Debug_logfile == -1) {
|
||
|
Debug_MessageBox(OSMBOX_OK, "Debug", "FYI Logfile couldn't be created.");
|
||
|
return false;
|
||
|
}
|
||
|
atexit(Debug_LogClose);
|
||
|
}
|
||
|
Debug_LogWrite("BEGINNING LOG\n\n");
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
void Debug_LogWrite(const char *str)
|
||
|
{
|
||
|
if (Debug_logfile > -1)
|
||
|
write(Debug_logfile, str, strlen(str));
|
||
|
}
|
||
|
|
||
|
void Debug_LogClose()
|
||
|
{
|
||
|
if (Debug_logfile > -1) {
|
||
|
Debug_LogWrite("\nEND LOG");
|
||
|
close(Debug_logfile);
|
||
|
Debug_logfile = -1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//void Debug_SetSpewFilter(uint spew_filter)
|
||
|
void Debug_SetSpewFilter(uint)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//uint Debug_GetSpewFilter(uint spew_filter)
|
||
|
uint Debug_GetSpewFilter(uint)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void Debug_ConsoleExit()
|
||
|
{
|
||
|
if(Console_fd>=0)
|
||
|
close(Console_fd);
|
||
|
Console_fd = -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
#define MAX_ARGS 30
|
||
|
#define MAX_CHARS_PER_ARG 100
|
||
|
extern char GameArgs[MAX_ARGS][MAX_CHARS_PER_ARG];
|
||
|
int FindArg (char *which);
|
||
|
|
||
|
bool Debug_ConsoleInit()
|
||
|
{
|
||
|
int n=0;
|
||
|
|
||
|
if (Mono_initialized)
|
||
|
return 1;
|
||
|
|
||
|
//Only use monochrome if D3_MONO environment var is set
|
||
|
atexit(Debug_ConsoleExit);
|
||
|
|
||
|
Console_fd = open("/dev/omono",O_WRONLY);
|
||
|
if(Console_fd>=0)
|
||
|
{
|
||
|
Mono_use_real = true;
|
||
|
Mono_initialized = 1;
|
||
|
}
|
||
|
|
||
|
int arg;
|
||
|
if((arg = FindArg("-monotcp"))!=0)
|
||
|
{
|
||
|
char address[256];
|
||
|
strcpy(address,GameArgs[arg+1]);
|
||
|
char *port_ptr;
|
||
|
port_ptr = strchr(address,':');
|
||
|
if(port_ptr)
|
||
|
{
|
||
|
*port_ptr = '\0';
|
||
|
port_ptr++;
|
||
|
unsigned short port;
|
||
|
port = atoi(port_ptr);
|
||
|
if(nw_InitTCPLogging(address,port))
|
||
|
{
|
||
|
Mono_use_window_remote = true;
|
||
|
Mono_initialized = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void Debug_ConsoleRedirectMessages(int virtual_window, int physical_window)
|
||
|
{
|
||
|
if(!Mono_initialized)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
0x02 Redirect Messages
|
||
|
|
||
|
Parameters:
|
||
|
Offset Size Value Description
|
||
|
====== ==== ===== ===========
|
||
|
0x01 0x01 0-7 Virtual window handle to be associated with physical window
|
||
|
0x02 0x01 0-3 Window handle to be redirected
|
||
|
*/
|
||
|
//create the packet and send it off
|
||
|
unsigned char packet[3];
|
||
|
packet[0x00] = 0x02; //control code
|
||
|
packet[0x01] = virtual_window; //virtual_handle
|
||
|
packet[0x02] = physical_window; //physical_handle
|
||
|
|
||
|
//send the packet
|
||
|
if(Mono_use_real)
|
||
|
{
|
||
|
write(Console_fd,packet,3);
|
||
|
}
|
||
|
if(Mono_use_window_remote)
|
||
|
{
|
||
|
nw_SendMonoPacket(packet,3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Debug_ConsoleOpen(int n, int row, int col, int width, int height, char * title )
|
||
|
{
|
||
|
if(!Mono_initialized)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
0x00 Open a window
|
||
|
|
||
|
Parameters:
|
||
|
Offset Size Value Description
|
||
|
====== ==== ===== ===========
|
||
|
0x01 0x01 0-3 Window handle to be associated with window
|
||
|
0x02 0x01 0-23 Upper left corner row value
|
||
|
0x03 0x01 0-78 Upper left corner col value
|
||
|
0x04 0x01 1-79 Number of cols (width)
|
||
|
0x05 0x01 1-24 Number of rows (height)
|
||
|
0x06 0x01 1-255 Length of the title string
|
||
|
0x07-> [0x06] ---- Title string (not \0 terminated)
|
||
|
*/
|
||
|
|
||
|
//create the packet and send it off
|
||
|
unsigned char packet[512];
|
||
|
int len = (title)?strlen(title):1;
|
||
|
packet[0x00] = 0x00; //control code
|
||
|
packet[0x01] = n; //window_handle
|
||
|
packet[0x02] = row; //row
|
||
|
packet[0x03] = col; //col
|
||
|
packet[0x04] = width;//width
|
||
|
packet[0x05] = height;//height
|
||
|
packet[0x06] = len;
|
||
|
if(title)
|
||
|
memcpy(&packet[0x07],title,len);
|
||
|
else
|
||
|
packet[0x07] = ' ';
|
||
|
|
||
|
//send the packet
|
||
|
if(Mono_use_real)
|
||
|
{
|
||
|
write(Console_fd,packet,len+7);
|
||
|
}
|
||
|
if(Mono_use_window_remote)
|
||
|
{
|
||
|
nw_SendMonoPacket(packet,len+7);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void Debug_ConsoleClose(int n)
|
||
|
{
|
||
|
if(!Mono_initialized)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
0x01 Closes a window
|
||
|
|
||
|
Parameters:
|
||
|
Offset Size Value Description
|
||
|
====== ==== ===== ===========
|
||
|
0x01 0x01 0-3 Window handle to be associated with window
|
||
|
|
||
|
*/
|
||
|
//create the packet and send it off
|
||
|
unsigned char packet[2];
|
||
|
packet[0x00] = 0x01; //control code
|
||
|
packet[0x01] = n; //window_handle
|
||
|
|
||
|
//send the packet
|
||
|
if(Mono_use_real)
|
||
|
{
|
||
|
write(Console_fd,packet,2);
|
||
|
}
|
||
|
if(Mono_use_window_remote)
|
||
|
{
|
||
|
nw_SendMonoPacket(packet,2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define MAX_MONO_BUFFER 2048
|
||
|
#else
|
||
|
#define MAX_MONO_BUFFER 32
|
||
|
#endif
|
||
|
static char Mono_buffer[MAX_MONO_BUFFER];
|
||
|
void Debug_ConsolePrintf( int n, char * format, ... )
|
||
|
{
|
||
|
va_list marker;
|
||
|
va_start(marker,format);
|
||
|
int text_len = vsnprintf(Mono_buffer,MAX_MONO_BUFFER,format,marker);
|
||
|
va_end(marker);
|
||
|
|
||
|
if( n == 0 )
|
||
|
{
|
||
|
printf("%s", Mono_buffer);
|
||
|
|
||
|
int end = strlen(Mono_buffer) - 1;
|
||
|
if((end > 1) && (Mono_buffer[end]!=0x0a) && (Mono_buffer[end]!=0x0d))
|
||
|
{
|
||
|
printf("\n");
|
||
|
}
|
||
|
}
|
||
|
nw_TCPPrintf(n,Mono_buffer);
|
||
|
|
||
|
if(!Mono_initialized)
|
||
|
return;
|
||
|
|
||
|
/*
|
||
|
0x03 Window Print at cursor position
|
||
|
|
||
|
Parameters:
|
||
|
Offset Size Value Description
|
||
|
====== ==== ===== ===========
|
||
|
0x01 0x01 0-3 Window handle to be associated with window
|
||
|
0x02 0x02 0-512 (Little Endian) Length of the text string
|
||
|
0x04 [0x02] ---- Text string (not \0 terminated)
|
||
|
*/
|
||
|
|
||
|
//create the packet and send it off
|
||
|
text_len = min(text_len,512);
|
||
|
unsigned char packet[518];
|
||
|
packet[0x00] = 0x03; //control code
|
||
|
packet[0x01] = n; //window_handle
|
||
|
*((unsigned short *)&packet[0x02]) = text_len;
|
||
|
memcpy(&packet[0x04],Mono_buffer,text_len);
|
||
|
|
||
|
//send the packet
|
||
|
if(Mono_use_real)
|
||
|
{
|
||
|
write(Console_fd,packet,text_len+4);
|
||
|
}
|
||
|
if(Mono_use_window_remote)
|
||
|
{
|
||
|
nw_SendMonoPacket(packet,text_len+4);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void Debug_ConsolePrintf( int n, int row, int col, char * format, ... )
|
||
|
{
|
||
|
if(!Mono_initialized)
|
||
|
return;
|
||
|
|
||
|
va_list marker;
|
||
|
va_start(marker,format);
|
||
|
int text_len = vsnprintf(Mono_buffer,MAX_MONO_BUFFER,format,marker);
|
||
|
va_end(marker);
|
||
|
|
||
|
/*
|
||
|
0x04 Window Print at row/col given
|
||
|
|
||
|
Parameters:
|
||
|
Offset Size Value Description
|
||
|
====== ==== ===== ===========
|
||
|
0x01 0x01 0-3 Window handle to be associated with window
|
||
|
0x02 0x01 0-24 Starting row (relative to window) of text
|
||
|
0x03 0x01 0-79 Starting col (relative to window) of text
|
||
|
0x04 0x02 0-512 (Little Endian) Length of the text string
|
||
|
0x06 [0x04] ---- Text string (not \0 terminated)
|
||
|
*/
|
||
|
//create the packet and send it off
|
||
|
unsigned char packet[518];
|
||
|
text_len = min(text_len,512);
|
||
|
packet[0x00] = 0x04; //control code
|
||
|
packet[0x01] = n; //window_handle
|
||
|
packet[0x02] = row; //row
|
||
|
packet[0x03] = col; //col
|
||
|
*((unsigned short *)&packet[0x04]) = text_len;
|
||
|
memcpy(&packet[0x06],Mono_buffer,text_len);
|
||
|
|
||
|
//send the packet
|
||
|
if(Mono_use_real)
|
||
|
{
|
||
|
write(Console_fd,packet,text_len+6);
|
||
|
}
|
||
|
if(Mono_use_window_remote)
|
||
|
{
|
||
|
//we can't send these to a mono server, they flood us
|
||
|
//nw_SendMonoPacket(packet,text_len+6);
|
||
|
}
|
||
|
}
|