nanoxwin.c

来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 1,548 行 · 第 1/3 页

C
1,548
字号
/* -*- c-basic-offset: 8 -*-
   rdesktop: A Remote Desktop Protocol client.
   User interface services - NanoX(microwindows)
   Copyright (C) Jay Sorg 2004-2005

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
  problems with nanox lib
    opcodes don't work, can only rely on copy
    stipple orgins don't work
    clip seems to affect source too, it should only affect dest
      in copyarea functions
*/

#include "../rdesktop.h"

#include <stdarg.h>  /* va_list va_start va_end */
#include <unistd.h> /* gethostname */
#include <pwd.h> /* getpwuid */

#include <nano-X.h>

extern int g_tcp_port_rdp;
int g_use_rdp5 = 1;
char g_hostname[16];
char g_username[64];
int g_width = 800;
int g_height = 600;
int g_server_bpp = 16;
int g_encryption = 1;
int g_desktop_save = 0; /* todo */
int g_polygon_ellipse_orders = 0;
int g_bitmap_cache = 1;
int g_bitmap_cache_persist_enable = 0;
int g_bitmap_cache_precache = 1;
int g_bitmap_compression = 1;
uint32 g_rdp5_performanceflags =
  RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
int g_console_session = 0;
int g_keylayout = 0x409; /* Defaults to US keyboard layout */
int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */
int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */
int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */

static int g_sck = 0;
static char g_servername[256] = "";
static char g_password[64] = "";
static char g_domain[64] = "";
static char g_shell[64] = "";
static char g_directory[64] = "";
static GR_WINDOW_ID g_wnd = 0;
static GR_GC_ID g_gc = 0;
static GR_GC_ID g_gc_clean = 0;
static int g_deactivated = 0;
static int g_ext_disc_reason = 0;
static GR_SCREEN_INFO g_screen_info;
static int g_bpp = 0;
static int g_Bpp = 0;
static GR_RECT g_clip; /* set in main */
static GR_CURSOR_ID g_null_cursor; /* set in main */
static int g_flags = RDP_LOGON_NORMAL;

struct key
{
  int ch1;
  int ch2;
  int ch3;
  int chs; /* shift char */
};

static struct key g_keys[256];

/* Session Directory redirection */
BOOL g_redirect = False;
char g_redirect_server[64];
char g_redirect_domain[16];
char g_redirect_password[64];
char g_redirect_username[64];
char g_redirect_cookie[128];
uint32 g_redirect_flags = 0;

#define COLOR16TO32(color) \
( \
  ((((color >> 8) & 0xf8) | ((color >> 13) & 0x7)) <<  0) | \
  ((((color >> 3) & 0xfc) | ((color >>  9) & 0x3)) <<  8) | \
  ((((color << 3) & 0xf8) | ((color >>  2) & 0x7)) << 16) \
)

static uint32 g_ops[16] =
{
  GR_MODE_CLEAR,         /* 0 */
  GR_MODE_NOR,           /* ~(src | dst) */
  GR_MODE_ANDINVERTED,   /* (~src) & dst */
  GR_MODE_COPYINVERTED,  /* ~src */
  GR_MODE_ANDREVERSE,    /* src & (~dst) */
  GR_MODE_INVERT,        /* ~(dst) */
  GR_MODE_XOR,           /* src ^ dst */
  GR_MODE_NAND,          /* ~(src & dst) */
  GR_MODE_AND,           /* src & dst */
  GR_MODE_EQUIV,         /* ~(src) ^ dst or is it ~(src ^ dst) */
  GR_MODE_NOOP,          /* dst */
  GR_MODE_ORINVERTED,    /* (~src) | dst */
  GR_MODE_COPY,          /* src */
  GR_MODE_ORREVERSE,     /* src | (~dst) */
  GR_MODE_OR,            /* src | dst */
  GR_MODE_SETTO1         /* ~0 */
};

/*****************************************************************************/
/* do a raster op */
static int rop(int rop, int src, int dst)
{
  switch (rop)
  {
    case 0x0: return 0;
    case 0x1: return ~(src | dst);
    case 0x2: return (~src) & dst;
    case 0x3: return ~src;
    case 0x4: return src & (~dst);
    case 0x5: return ~(dst);
    case 0x6: return src ^ dst;
    case 0x7: return ~(src & dst);
    case 0x8: return src & dst;
    case 0x9: return ~(src) ^ dst;
    case 0xa: return dst;
    case 0xb: return (~src) | dst;
    case 0xc: return src;
    case 0xd: return src | (~dst);
    case 0xe: return src | dst;
    case 0xf: return ~0;
  }
  return dst;
}

/*****************************************************************************/
static int get_pixel32(uint8 * data, int x, int y,
                       int width, int height)
{
  if (x >= 0 && y >= 0 && x < width && y < height)
  {
    return *(((int*)data) + (y * width + x));
  }
  else
  {
    return 0;
  }
}

/*****************************************************************************/
static void set_pixel32(uint8 * data, int x, int y,
                        int width, int height, int pixel)
{
  if (x >= 0 && y >= 0 && x < width && y < height)
  {
    *(((int*)data) + (y * width + x)) = pixel;
  }
}

/*****************************************************************************/
static int warp_coords(int * x, int * y, int * cx, int * cy,
                       int * srcx, int * srcy)
{
  int dx;
  int dy;

  if (g_clip.x > *x)
  {
    dx = g_clip.x - *x;
  }
  else
  {
    dx = 0;
  }
  if (g_clip.y > *y)
  {
    dy = g_clip.y - *y;
  }
  else
  {
    dy = 0;
  }
  if (*x + *cx > g_clip.x + g_clip.width)
  {
    *cx = (*cx - ((*x + *cx) - (g_clip.x + g_clip.width)));
  }
  if (*y + *cy > g_clip.y + g_clip.height)
  {
    *cy = (*cy - ((*y + *cy) - (g_clip.y + g_clip.height)));
  }
  *cx = *cx - dx;
  *cy = *cy - dy;
  if (*cx <= 0)
  {
    return 0;
  }
  if (*cy <= 0)
  {
    return 0;
  }
  *x = *x + dx;
  *y = *y + dy;
  if (srcx != 0)
  {
    *srcx = *srcx + dx;
  }
  if (srcy != 0)
  {
    *srcy = *srcy + dy;
  }
  return 1;
}

/******************************************************************************/
/* check if a certain pixel is set in a bitmap */
static int is_pixel_on(uint8 * data, int x, int y, int width, int bpp)
{
  int start;
  int shift;

  if (bpp == 1)
  {
    width = (width + 7) / 8;
    start = (y * width) + x / 8;
    shift = x % 8;
    return (data[start] & (0x80 >> shift)) != 0;
  }
  else
    return 0;
}

/*****************************************************************************/
int ui_select(int in)
{
  if (g_sck == 0)
  {
    g_sck = in;
  }
  return 1;
}

/*****************************************************************************/
void ui_set_clip(int x, int y, int cx, int cy)
{
  GR_REGION_ID region;

  g_clip.x = x;
  g_clip.y = y;
  g_clip.width = cx;
  g_clip.height = cy;
  region = GrNewRegion();
  GrUnionRectWithRegion(region, &g_clip);
  GrSetGCRegion(g_gc, region); /* can't destroy region here, i guess gc */
                               /* takes owership, if you destroy it */
                               /* clip is reset, hum */
}

/*****************************************************************************/
void ui_reset_clip(void)
{
  GrSetGCRegion(g_gc, 0);
  g_clip.x = 0;
  g_clip.y = 0;
  g_clip.width = g_width;
  g_clip.height = g_height;
}

/*****************************************************************************/
void ui_bell(void)
{
  GrBell();
}

/*****************************************************************************/
/* gota convert the rdp glyph to nanox glyph */
void * ui_create_glyph(int width, int height, uint8 * data)
{
  char * p, * q, * r;
  int datasize, i, j;

  datasize = GR_BITMAP_SIZE(width, height) * sizeof(GR_BITMAP);
  p = xmalloc(datasize);
  q = p;
  r = data;
  memset(p, 0, datasize);
  for (i = 0; i < height; i++)
  {
    j = 0;
    while (j + 8 < width)
    {
      *q = *(r + 1);
      q++;
      r++;
      *q = *(r - 1);
      q++;
      r++;
      j += 16;
    }
    if ((width % 16) <= 8 && (width % 16) > 0)
    {
      q++;
      *q = *r;
      q++;
      r++;
      j += 8;
    }
  }
  return p;
}

/*****************************************************************************/
void ui_destroy_glyph(void * glyph)
{
  xfree(glyph);
}

/*****************************************************************************/
void * ui_create_colourmap(COLOURMAP * colors)
{
  return 0;
}

/*****************************************************************************/
void ui_set_colourmap(void * map)
{
}

/*****************************************************************************/
void * ui_create_bitmap(int width, int height, uint8 * data)
{
  GR_WINDOW_ID pixmap;
  uint8 * p;
  uint32 i, j, pixel;

  p = data;
  pixmap = GrNewPixmap(width, height, 0);
  if (g_server_bpp == 16 && g_bpp == 32)
  {
    p = xmalloc(width * height * g_Bpp);
    for (i = 0; i < height; i++)
    {
      for (j = 0; j < width; j++)
      {
        pixel = *(((uint16 *) data) + (i * width + j));
        pixel = COLOR16TO32(pixel);
        *(((uint32 *) p) + (i * width + j)) = pixel;
      }
    }
  }
  GrArea(pixmap, g_gc_clean, 0, 0, width, height, p, MWPF_RGB);
  if (p != data)
  {
    xfree(p);
  }
  return (void *) pixmap;
}

/*****************************************************************************/
void ui_destroy_bitmap(void * bmp)
{
  GrDestroyWindow((GR_WINDOW_ID)bmp);
}

/*****************************************************************************/
#define DO_GLYPH(ttext,idx) \
{ \
  glyph = cache_get_font (font, ttext[idx]); \
  if (!(flags & TEXT2_IMPLICIT_X)) \
  { \
    xyoffset = ttext[++idx]; \
    if ((xyoffset & 0x80)) \
    { \
      if (flags & TEXT2_VERTICAL) \
      { \
        y += ttext[idx+1] | (ttext[idx+2] << 8); \
      } \
      else \
      { \
        x += ttext[idx+1] | (ttext[idx+2] << 8); \
      } \
      idx += 2; \
    } \
    else \
    { \
      if (flags & TEXT2_VERTICAL) \
      { \
        y += xyoffset; \
      } \
      else \
      { \
        x += xyoffset; \
      } \
    } \
  } \
  if (glyph != NULL) \
  { \
    x1 = x + glyph->offset; \
    y1 = y + glyph->baseline; \
    GrBitmap(g_wnd, g_gc, x1, y1, glyph->width, glyph->height, glyph->pixmap); \
    if (flags & TEXT2_IMPLICIT_X) \
    { \
      x += glyph->width; \
    } \
  } \
}

/*****************************************************************************/
void ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode,
                  int x, int y,
                  int clipx, int clipy, int clipcx, int clipcy,
                  int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
                  int bgcolor, int fgcolor, uint8 * text, uint8 length)
{
  FONTGLYPH * glyph;
  int i, j, xyoffset, x1, y1;
  DATABLOB * entry;

  GrSetGCMode(g_gc, GR_MODE_COPY);
  GrSetGCUseBackground(g_gc, 0); /* this can be set when gc is created */
  if (g_server_bpp == 16 && g_bpp == 32)
  {
    fgcolor = COLOR16TO32(fgcolor);
    bgcolor = COLOR16TO32(bgcolor);
  }
  GrSetGCForeground(g_gc, bgcolor);
  if (boxx + boxcx > g_width)
  {
    boxcx = g_width - boxx;
  }
  if (boxcx > 1)
  {
    GrFillRect(g_wnd, g_gc, boxx, boxy, boxcx, boxcy);
  }
  else if (mixmode == MIX_OPAQUE)
  {
    GrFillRect(g_wnd, g_gc, clipx, clipy, clipcx, clipcy);
  }
  GrSetGCForeground(g_gc, fgcolor);
  /* Paint text, character by character */
  for (i = 0; i < length;)
  {
    switch (text[i])
    {
      case 0xff:
        if (i + 2 < length)
        {
          cache_put_text(text[i + 1], text, text[i + 2]);
        }
        else
        {
          error("this shouldn't be happening\n");
          exit(1);
        }
        /* this will move pointer from start to first character after */
        /* FF command */
        length -= i + 3;
        text = &(text[i + 3]);
        i = 0;
        break;
      case 0xfe:
        entry = cache_get_text(text[i + 1]);
        if (entry != NULL)
        {
          if ((((uint8 *) (entry->data))[1] == 0) &&
                                (!(flags & TEXT2_IMPLICIT_X)))
          {
            if (flags & TEXT2_VERTICAL)
            {
              y += text[i + 2];
            }
            else
            {
              x += text[i + 2];
            }
          }
          for (j = 0; j < entry->size; j++)
          {
            DO_GLYPH(((uint8 *) (entry->data)), j);
          }
        }
        if (i + 2 < length)
        {
          i += 3;
        }
        else
        {
          i += 2;
        }
        length -= i;
        /* this will move pointer from start to first character after */
        /* FE command */
        text = &(text[i]);
        i = 0;
        break;
      default:
        DO_GLYPH(text, i);
        i++;
        break;
    }
  }
}

/*****************************************************************************/
void ui_line(uint8 opcode, int startx, int starty, int endx, int endy,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?