Permalink
Browse files

Move dialog to Window, simplify Options/EntryList

  • Loading branch information...
UnknownShadow200 committed Nov 27, 2018
1 parent 04c3683 commit 718aa1b3d182d5fd3459a5955f361d25a712c3d1
Showing with 501 additions and 527 deletions.
  1. +2 −1 src/Animations.c
  2. +0 −2 src/Animations.h
  3. +1 −261 src/ErrorHandler.c
  4. +0 −1 src/ErrorHandler.h
  5. +1 −6 src/Game.c
  6. +5 −5 src/Input.c
  7. +37 −105 src/Options.c
  8. +1 −3 src/Options.h
  9. +4 −4 src/Program.c
  10. +0 −5 src/ServerConnection.c
  11. +2 −1 src/ServerConnection.h
  12. +31 −133 src/TexturePack.c
  13. +137 −0 src/Utils.c
  14. +23 −0 src/Utils.h
  15. +255 −0 src/Window.c
  16. +2 −0 src/Window.h
@@ -304,7 +304,7 @@ static void Animations_Validate(void) {
}


void Animations_Tick(struct ScheduledTask* task) {
static void Animations_Tick(struct ScheduledTask* task) {
int i, size;

if (anims_useLavaAnim) {
@@ -359,6 +359,7 @@ static void Animations_FileChanged(void* obj, struct Stream* stream, const Strin
*--------------------------------------------------Animations component---------------------------------------------------*
*#########################################################################################################################*/
static void Animations_Init(void) {
ScheduledTask_Add(GAME_DEF_TICKS, Animations_Tick);
Event_RegisterVoid(&TextureEvents_PackChanged, NULL, Animations_PackChanged);
Event_RegisterEntry(&TextureEvents_FileChanged, NULL, Animations_FileChanged);
}
@@ -11,6 +11,4 @@
struct IGameComponent;
struct ScheduledTask;
extern struct IGameComponent Animations_Component;

void Animations_Tick(struct ScheduledTask* task);
#endif
@@ -201,10 +201,6 @@ void ErrorHandler_Init(void) {
SetUnhandledExceptionFilter(ErrorHandler_UnhandledFilter);
}

void ErrorHandler_ShowDialog(const char* title, const char* msg) {
MessageBoxA(Window_GetWindowHandle(), msg, title, 0);
}

/* Don't want compiler doing anything fancy with registers */
#if _MSC_VER
#pragma optimize ("", off)
@@ -344,250 +340,6 @@ void ErrorHandler_Fail2(ReturnCode result, const char* raw_msg) {
ErrorHandler_FailCommon(result, raw_msg, &ctx);
}
#endif
#ifdef CC_BUILD_X11
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>

/*########################################################################################################################*
*-----------------------------------------------------X11 message box-----------------------------------------------------*
*#########################################################################################################################*/
Display* dpy;
unsigned long X11_Col(uint8_t r, uint8_t g, uint8_t b) {
Colormap cmap = XDefaultColormap(dpy, DefaultScreen(dpy));
XColor col = { 0 };
col.red = r << 8;
col.green = g << 8;
col.blue = b << 8;
col.flags = DoRed | DoGreen | DoBlue;

XAllocColor(dpy, cmap, &col);
return col.pixel;
}

typedef struct {
Window win;
GC gc;
unsigned long white, black, background;
unsigned long btnBorder, highlight, shadow;
} X11Window;

static void X11Window_Init(X11Window* w) {
w->black = BlackPixel(dpy, DefaultScreen(dpy));
w->white = WhitePixel(dpy, DefaultScreen(dpy));
w->background = X11_Col(206, 206, 206);

w->btnBorder = X11_Col(60, 60, 60);
w->highlight = X11_Col(144, 144, 144);
w->shadow = X11_Col(49, 49, 49);

w->win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 100, 100,
0, w->black, w->background);
XSelectInput(dpy, w->win, ExposureMask | StructureNotifyMask |
KeyReleaseMask | PointerMotionMask |
ButtonPressMask | ButtonReleaseMask );

w->gc = XCreateGC(dpy, w->win, 0, NULL);
XSetForeground(dpy, w->gc, w->black);
XSetBackground(dpy, w->gc, w->background);
}

static void X11Window_Free(X11Window* w) {
XFreeGC(dpy, w->gc);
XDestroyWindow(dpy, w->win);
}

typedef struct {
int X, Y, Width, Height;
int LineHeight, Descent;
const char* Text;
} X11Textbox;

static void X11Textbox_Measure(X11Textbox* t, XFontStruct* font) {
String str = String_FromReadonly(t->Text);
XCharStruct overall;
int direction, ascent, descent;
int end, len, lines = 0;

for (end = 0; end >= 0; lines++) {
end = String_IndexOf(&str, '\n', 0);
len = end == -1 ? str.length : end;

XTextExtents(font, str.buffer, len, &direction, &ascent, &descent, &overall);
t->Width = max(overall.width, t->Width);
if (end >= 0) str = String_UNSAFE_SubstringAt(&str, end + 1);
}

t->LineHeight = ascent + descent;
t->Descent = descent;
t->Height = t->LineHeight * lines;
}

static void X11Textbox_Draw(X11Textbox* t, X11Window* w) {
String str = String_FromReadonly(t->Text);
int y = t->Y + t->LineHeight - t->Descent; /* TODO: is -Descent even right? */
int end, len;

for (end = 0; end >= 0; y += t->LineHeight) {
end = String_IndexOf(&str, '\n', 0);
len = end == -1 ? str.length : end;

XDrawString(dpy, w->win, w->gc, t->X, y, str.buffer, len);
if (end >= 0) str = String_UNSAFE_SubstringAt(&str, end + 1);
}
}

typedef struct {
int X, Y, Width, Height;
bool Clicked;
X11Textbox Text;
} X11Button;

static void X11Button_Draw(X11Button* b, X11Window* w) {
X11Textbox* t;
int begX, endX, begY, endY;

XSetForeground(dpy, w->gc, w->btnBorder);
XDrawRectangle(dpy, w->win, w->gc, b->X, b->Y,
b->Width, b->Height);

t = &b->Text;
begX = b->X + 1; endX = b->X + b->Width - 1;
begY = b->Y + 1; endY = b->Y + b->Height - 1;

if (b->Clicked) {
XSetForeground(dpy, w->gc, w->highlight);
XDrawRectangle(dpy, w->win, w->gc, begX, begY,
endX - begX, endY - begY);
} else {
XSetForeground(dpy, w->gc, w->white);
XDrawLine(dpy, w->win, w->gc, begX, begY,
endX - 1, begY);
XDrawLine(dpy, w->win, w->gc, begX, begY,
begX, endY - 1);

XSetForeground(dpy, w->gc, w->highlight);
XDrawLine(dpy, w->win, w->gc, begX + 1, endY - 1,
endX - 1, endY - 1);
XDrawLine(dpy, w->win, w->gc, endX - 1, begY + 1,
endX - 1, endY - 1);

XSetForeground(dpy, w->gc, w->shadow);
XDrawLine(dpy, w->win, w->gc, begX, endY, endX, endY);
XDrawLine(dpy, w->win, w->gc, endX, begY, endX, endY);
}

XSetForeground(dpy, w->gc, w->black);
t->X = b->X + b->Clicked + (b->Width - t->Width) / 2;
t->Y = b->Y + b->Clicked + (b->Height - t->Height) / 2;
X11Textbox_Draw(t, w);
}

static int X11Button_Contains(X11Button* b, int x, int y) {
return x >= b->X && x < (b->X + b->Width) &&
y >= b->Y && y < (b->Y + b->Height);
}

static void X11_MessageBox(const char* title, const char* text, X11Window* w) {
X11Button ok = { 0 };
X11Textbox body = { 0 };

XFontStruct* font;
Atom wmDelete;
int x, y, width, height;
XSizeHints hints = { 0 };
int mouseX = -1, mouseY = -1, over;
XEvent e;

X11Window_Init(w);
XMapWindow(dpy, w->win);
XStoreName(dpy, w->win, title);

wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
XSetWMProtocols(dpy, w->win, &wmDelete, 1);

font = XQueryFont(dpy, XGContextFromGC(w->gc));
if (!font) return;

/* Compute size of widgets */
body.Text = text;
X11Textbox_Measure(&body, font);
ok.Text.Text = "OK";
X11Textbox_Measure(&ok.Text, font);
ok.Width = ok.Text.Width + 70;
ok.Height = ok.Text.Height + 10;

/* Compute size and position of window */
width = body.Width + 20;
height = body.Height + 20 + ok.Height + 20;
x = DisplayWidth (dpy, DefaultScreen(dpy))/2 - width/2;
y = DisplayHeight(dpy, DefaultScreen(dpy))/2 - height/2;
XMoveResizeWindow(dpy, w->win, x, y, width, height);

/* Adjust bounds of widgets */
body.X = 10; body.Y = 10;
ok.X = width/2 - ok.Width/2;
ok.Y = height - ok.Height - 10;

XFreeFontInfo(NULL, font, 1);
XUnmapWindow(dpy, w->win); /* Make window non resizeable */

hints.flags = PSize | PMinSize | PMaxSize;
hints.min_width = hints.max_width = hints.base_width = width;
hints.min_height = hints.max_height = hints.base_height = height;

XSetWMNormalHints(dpy, w->win, &hints);
XMapRaised(dpy, w->win);
XFlush(dpy);

for (;;) {
XNextEvent(dpy, &e);

switch (e.type)
{
case ButtonPress:
case ButtonRelease:
if (e.xbutton.button != Button1) break;
over = X11Button_Contains(&ok, mouseX, mouseY);

if (ok.Clicked && e.type == ButtonRelease) {
if (over) return;
}
ok.Clicked = e.type == ButtonPress && over;
/* fallthrough to redraw window */

case Expose:
case MapNotify:
XClearWindow(dpy, w->win);
X11Textbox_Draw(&body, w);
X11Button_Draw(&ok, w);
XFlush(dpy);
break;

case KeyRelease:
if (XLookupKeysym(&e.xkey, 0) == XK_Escape) return;
break;

case ClientMessage:
if (e.xclient.data.l[0] == wmDelete) return;
break;

case MotionNotify:
mouseX = e.xmotion.x; mouseY = e.xmotion.y;
break;
}
}
}

void ErrorHandler_ShowDialog(const char* title, const char* msg) {
X11Window w = { 0 };
dpy = DisplayDevice_Meta;

X11_MessageBox(title, msg, &w);
X11Window_Free(&w);
}
#endif


/*########################################################################################################################*
@@ -679,18 +431,6 @@ static void ErrorHandler_DumpCommon(String* str, void* ctx) {
ErrorHandler_Log(&backtrace);
ErrorHandler_Backtrace(str, ctx);
}

void ErrorHandler_ShowDialog(const char* title, const char* msg) {
CFStringRef titleCF = CFStringCreateWithCString(NULL, title, kCFStringEncodingASCII);
CFStringRef msgCF = CFStringCreateWithCString(NULL, msg, kCFStringEncodingASCII);
DialogRef dialog;
DialogItemIndex itemHit;

CreateStandardAlert(kAlertPlainAlert, titleCF, msgCF, NULL, &dialog);
CFRelease(titleCF);
CFRelease(msgCF);
RunStandardAlert(dialog, NULL, &itemHit);
}
#endif


@@ -736,7 +476,7 @@ static void ErrorHandler_FailCommon(ReturnCode result, const char* raw_msg, void
String_AppendConst(&msg, "Please report the crash on the ClassiCube forums so we can fix it.");

msg.buffer[msg.length] = '\0';
ErrorHandler_ShowDialog("We're sorry", msg.buffer);
Window_ShowDialog("We're sorry", msg.buffer);
Platform_Exit(result);
}

@@ -11,5 +11,4 @@ void ErrorHandler_Log(const String* msg);
void ErrorHandler_Fail(const char* raw_msg);
CC_NOINLINE void ErrorHandler_Fail2(ReturnCode result, const char* raw_msg);
#define ErrorHandler_CheckOrFail(result, raw_msg) if (result) { ErrorHandler_Fail2(result, raw_msg); }
CC_NOINLINE void ErrorHandler_ShowDialog(const char* title, const char* msg);
#endif
@@ -433,11 +433,6 @@ static void Game_LoadGuiOptions(void) {
/* TODO: Handle Arial font not working */
}

static void Game_InitScheduledTasks(void) {
entTaskI = ScheduledTask_Add(GAME_DEF_TICKS, Entities_Tick);
ScheduledTask_Add(GAME_DEF_TICKS, Animations_Tick);
}

void Game_Free(void* obj);
void Game_Load(void) {
String title; char titleBuffer[STRING_SIZE];
@@ -517,8 +512,8 @@ void Game_Load(void) {
for (comp = comps_head; comp; comp = comp->Next) {
if (comp->Ready) comp->Ready();
}
Game_InitScheduledTasks();

entTaskI = ScheduledTask_Add(GAME_DEF_TICKS, Entities_Tick);
/* TODO: plugin dll support */
/* if (nonLoaded != null) {
for (int i = 0; i < nonLoaded.Count; i++) {
@@ -316,20 +316,20 @@ int Hotkeys_FindPartial(Key key) {
void Hotkeys_Init(void) {
static String prefix = String_FromConst("hotkey-");
String strKey, strMods, strMore, strText;
String key, value;
String entry, key, value;
int i;

Key trigger;
uint8_t modifiers;
bool more;

for (i = 0; i < Options_Keys.Count; i++) {
key = StringsBuffer_UNSAFE_Get(&Options_Keys, i);
if (!String_CaselessStarts(&key, &prefix)) continue;
for (i = 0; i < Options.Entries.Count; i++) {
entry = StringsBuffer_UNSAFE_Get(&Options.Entries, i);
String_UNSAFE_Separate(&entry, Options.Separator, &key, &value);

if (!String_CaselessStarts(&key, &prefix)) continue;
/* Format is: key&modifiers = more-input&text */
key.length -= prefix.length; key.buffer += prefix.length;
value = StringsBuffer_UNSAFE_Get(&Options_Values, i);

if (!String_UNSAFE_Separate(&key, '&', &strKey, &strMods)) continue;
if (!String_UNSAFE_Separate(&value, '&', &strMore, &strText)) continue;
Oops, something went wrong.

0 comments on commit 718aa1b

Please sign in to comment.